switch to CMake

This commit is contained in:
Martin Michelsen
2021-12-29 11:51:17 -08:00
parent 6b5766449e
commit e8f23e4b2e
62 changed files with 253 additions and 326 deletions
+12 -1
View File
@@ -1,3 +1,14 @@
# Finder files (macOS)
.DS_Store .DS_Store
*.o
# Build products
newserv newserv
# CMake files
CMakeCache.txt
CMakeFiles
Makefile
CTestTestFile.cmake
Testing
cmake_install.cmake
install_manifest.txt
+72
View File
@@ -0,0 +1,72 @@
cmake_minimum_required(VERSION 3.10)
# Project setup
project(newserv)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
if (MSVC)
add_compile_options(/W4 /WX)
else()
add_compile_options(-Wall -Wextra -Werror)
endif()
include_directories("/usr/local/include")
link_directories("/usr/local/lib")
# Executable definitions
find_path (LIBEVENT_INCLUDE_DIR NAMES event.h)
find_library (LIBEVENT_LIBRARY NAMES event)
find_library (LIBEVENT_CORE NAMES event_core)
find_library (LIBEVENT_THREAD NAMES event_pthreads)
set (LIBEVENT_INCLUDE_DIRS ${LIBEVENT_INCLUDE_DIR})
set (LIBEVENT_LIBRARIES
${LIBEVENT_LIBRARY}
${LIBEVENT_CORE}
${LIBEVENT_THREAD})
add_executable(newserv
src/FileContentsCache.cc
src/Menu.cc
src/PSOProtocol.cc
src/Client.cc
src/Lobby.cc
src/ServerState.cc
src/Server.cc
src/License.cc
src/PSOEncryption.cc
src/Player.cc
src/SendCommands.cc
src/ChatCommands.cc
src/ReceiveSubcommands.cc
src/ReceiveCommands.cc
src/Version.cc
src/Items.cc
src/LevelTable.cc
src/Compression.cc
src/Quest.cc
src/RareItemSet.cc
src/Map.cc
src/NetworkAddresses.cc
src/Text.cc
src/DNSServer.cc
src/ProxyServer.cc
src/Shell.cc
src/ServerShell.cc
src/ProxyShell.cc
src/Main.cc
)
target_include_directories(newserv PUBLIC ${LIBEVENT_INCLUDE_DIR})
target_link_libraries(newserv phosg ${LIBEVENT_LIBRARIES})
# Installation configuration
install(TARGETS newserv DESTINATION bin)
-19
View File
@@ -1,19 +0,0 @@
OBJECTS=FileContentsCache.o Menu.o PSOProtocol.o Client.o Lobby.o \
ServerState.o Server.o License.o PSOEncryption.o Player.o SendCommands.o \
ChatCommands.o ReceiveSubcommands.o ReceiveCommands.o Version.o Items.o \
LevelTable.o Compression.o Quest.o RareItemSet.o Map.o NetworkAddresses.o \
Text.o DNSServer.o ProxyServer.o Shell.o ServerShell.o ProxyShell.o Main.o
CXX=g++
CXXFLAGS=-I/opt/homebrew/include -I/opt/local/include -I/usr/local/include -std=c++20 -g -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -Wall -Werror
LDFLAGS=-L/opt/homebrew/lib -L/opt/local/lib -L/usr/local/lib -std=c++20 -levent -levent_pthreads -lphosg -lpthread
all: newserv
newserv: $(OBJECTS)
$(CXX) $(OBJECTS) $(LDFLAGS) -o newserv
clean:
find . -name \*.o -delete
rm -rf *.dSYM newserv newserv-dns gmon.out
.PHONY: clean test
-137
View File
@@ -1,137 +0,0 @@
#!/bin/env python3
import argparse
import os
import pwd
import re
import stat
import subprocess
import sys
import time
def change_user(username):
try:
user_info = pwd.getpwnam(username)
except KeyError:
print("user %s does not exist" % (username,))
raise
os.setregid(user_info.pw_gid, user_info.pw_gid)
os.setreuid(user_info.pw_uid, user_info.pw_uid)
def main(argv):
parser = argparse.ArgumentParser(description="Runs Dolphin as a non-privileged user with access to the privileged tap0 network interface. Run this script with sudo; it will run Dolphin as the user you sudo'ed from and provide it access to the tap interface. It will also automatically configure the tap interface when Dolphin first opens it.")
parser.add_argument(
"--dolphin-path", "-d",
action="store",
dest="dolphin_path",
default="./Dolphin.app/Contents/MacOS/Dolphin",
help="Path to Dolphin executable. Defaults to Dolphin.app/Contents/MacOS/Dolphin in current directory.",
)
parser.add_argument(
"--memwatch-path", "-m",
action="store",
dest="memwatch_path",
default="memwatch",
help="Path to memwatch executable. Defaults to memwatch (assumes it's installed somewhere on $PATH).",
)
parser.add_argument(
"--tap-interface", "-I",
action="store",
dest="tap_interface",
default="/dev/tap0",
help="Tap interface to use. Defaults to /dev/tap0.",
)
parser.add_argument(
"--tap-ip", "-i",
action="store",
dest="tap_ip",
default="192.168.0.5/24",
help="IP address and subnet bits to assign to tap interface. Defaults to 192.168.0.5/24. This should match the gateway and DNS server addresses configured in PSO's network settings.",
)
args = parser.parse_args()
try:
username = os.environ['SUDO_USER']
except KeyError:
print('$SUDO_USER not set; use `sudo -E`')
return 1
tap_match = re.match(r'^/dev/tap([0-9]+)$', args.tap_interface)
if tap_match is None:
print('tap interface name must begin with /dev/tap')
return 1
tap_interface_number = int(tap_match.group(1))
tap_name = 'tap%d' % (tap_interface_number,)
# 1. open tap and configure it
print("starting and configuring " + tap_name)
tap_fd = os.open(args.tap_interface, os.O_RDWR)
os.set_inheritable(tap_fd, True)
subprocess.check_call(['ifconfig', tap_name, args.tap_ip], stderr=subprocess.DEVNULL)
subprocess.check_call(['ifconfig', tap_name, 'up'], stderr=subprocess.DEVNULL)
subprocess.check_call(['ifconfig', tap_name, 'mtu', '9000'], stderr=subprocess.DEVNULL)
# 2. fork a Dolphin process, dropping privileges first
print("starting dolphin")
dolphin_proc = subprocess.Popen([args.dolphin_path],
preexec_fn=lambda: change_user(username), pass_fds=(tap_fd,))
time.sleep(1)
# 3. create a temp file for dolphin to open instead of /dev/tapN
print("creating temp file")
tmpfile_fd = os.open("/tmp/dnet", os.O_CREAT | os.O_RDWR, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
os.close(tmpfile_fd)
os.chmod("/tmp/dnet", stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
# 4. modify dolphin's memory to make it upen the temp file
print("redirecting /dev/tap0 for dolphin")
addresses_str = subprocess.check_output([args.memwatch_path, str(dolphin_proc.pid), 'find', '\"/dev/tap0\"'], stderr=subprocess.DEVNULL)
for line in addresses_str.splitlines():
tokens = line.split()
if len(tokens) != 3:
continue
print("redirecting /dev/tap0 to /tmp/dnet at %s in dolphin" % (tokens[1],))
subprocess.check_call([args.memwatch_path, str(dolphin_proc.pid), "access", tokens[1], "rwx"], stderr=subprocess.DEVNULL)
subprocess.check_call([args.memwatch_path, str(dolphin_proc.pid), "write", tokens[1], "\"/tmp/dnet\""], stderr=subprocess.DEVNULL)
subprocess.check_call([args.memwatch_path, str(dolphin_proc.pid), "access", tokens[1], "r-x"], stderr=subprocess.DEVNULL)
# step 5: use lsof to find out when dolphin opens /tmp/dnet
print("waiting for temp file to open")
dolphin_tap0_fd = -1
while dolphin_tap0_fd < 0:
time.sleep(1)
result = subprocess.check_output(["lsof", "-p", str(dolphin_proc.pid)], stderr=subprocess.DEVNULL)
for line in result.splitlines():
if b'/tmp/dnet' not in line:
continue
fd_str = line.split()[3]
dolphin_tap0_fd = int(fd_str[0:-len(fd_str.lstrip(b'0123456789'))])
print("found open tap fd %d in dolphin" % (dolphin_tap0_fd,))
# step 6: use memwatch to move the tap fd into place
print("replacing temp fd %d with tap fd %d in dolphin" % (dolphin_tap0_fd,
tap_fd))
assembly_contents = b"""start:
mov rax, 0x000000000200005A # dup2(from_fd, to_fd)
mov rdi, %d
mov rsi, %d
syscall
# close the original fd. note that rdi is preserved during the syscall so we
# don't need to reload it
mov rax, 0x0000000002000006 # close(fd)
syscall
ret
""" % (tap_fd, dolphin_tap0_fd)
subprocess.run([args.memwatch_path, str(dolphin_proc.pid), "--", "run", "-"], input=assembly_contents, stderr=subprocess.DEVNULL)
# ok we're done; dolphin is running as a non-privileged user with the tap open
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))
+3 -3
View File
@@ -27,9 +27,9 @@ This project is primarily for my own nostalgia. Feel free to peruse if you'd lik
Currently this code should build on macOS and Ubuntu. It might build on other Linux flavors, but don't expect it to work on Windows at all. Currently this code should build on macOS and Ubuntu. It might build on other Linux flavors, but don't expect it to work on Windows at all.
So, you've read all of the above and you want to try it out? Here's what you do: So, you've read all of the above and you want to try it out? Here's what you do:
- Make sure you have libevent installed (use Homebrew in macOS, or install libevent-dev in Linux). - Make sure you have CMake and libevent installed (use Homebrew in macOS, or install libevent-dev in Linux).
- Build and install phosg (https://github.com/fuzziqersoftware/phosg). - Build and install phosg (https://github.com/fuzziqersoftware/phosg).
- Run `make`. - Run `cmake . && make`.
- Edit system/config.json to your liking. - Edit system/config.json to your liking.
- Run `./newserv` in the newserv directory. This will start the game server and run the interactive shell. (You can disable the interactive shell later by editing config.json.) You may need `sudo` if newserv's built-in DNS server is enabled. - Run `./newserv` in the newserv directory. This will start the game server and run the interactive shell. (You can disable the interactive shell later by editing config.json.) You may need `sudo` if newserv's built-in DNS server is enabled.
- Use the interactive shell to add a license. Run `help` in the shell to see how to do this. - Use the interactive shell to add a license. Run `help` in the shell to see how to do this.
@@ -39,7 +39,7 @@ So, you've read all of the above and you want to try it out? Here's what you do:
If you're running PSO on a real GameCube, you can make PSO connect to newserv by changing its default gateway and DNS server addresses to newserv's address. If you're running PSO on a real GameCube, you can make PSO connect to newserv by changing its default gateway and DNS server addresses to newserv's address.
If you're emulating PSO GC using Dolphin on Mac OS (like I am), you can make it connect to newserv by doing this: If you're emulating PSO GC using Dolphin on Mac OS (like I am), you can make it connect to newserv by doing this:
- Use a build of Dolphin that has tapserver support (this may mean building it from master yourself). - Use a build of Dolphin that has tapserver support.
- Install tapserver (https://github.com/fuzziqersoftware/tapserver). - Install tapserver (https://github.com/fuzziqersoftware/tapserver).
- In PSO, manually configure your network settings as follows: IP address = `192.168.0.200`, subnet mask = `255.255.255.0`, default gateway = `192.168.0.5`, DNS server address 1 = `192.168.0.5`. - In PSO, manually configure your network settings as follows: IP address = `192.168.0.200`, subnet mask = `255.255.255.0`, default gateway = `192.168.0.5`, DNS server address 1 = `192.168.0.5`.
- Start Dolphin and newserv. - Start Dolphin and newserv.
+23 -24
View File
@@ -379,8 +379,8 @@ static void check_is_leader(shared_ptr<Lobby> l, shared_ptr<Client> c) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Message commands // Message commands
static void command_lobby_info(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_lobby_info(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t*) {
// no preconditions - everyone can use this command // no preconditions - everyone can use this command
if (!l) { if (!l) {
@@ -407,22 +407,21 @@ static void command_lobby_info(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
} }
} }
static void command_ax(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_ax(shared_ptr<ServerState>, shared_ptr<Lobby>,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_privileges(c, Privilege::Announce); check_privileges(c, Privilege::Announce);
log(INFO, "[$ax from %010u] %S\n", c->license->serial_number, args); log(INFO, "[$ax from %010u] %S\n", c->license->serial_number, args);
} }
static void command_announce(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_announce(shared_ptr<ServerState> s, shared_ptr<Lobby>,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_privileges(c, Privilege::Announce); check_privileges(c, Privilege::Announce);
send_text_message(s, args); send_text_message(s, args);
} }
static void command_arrow(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_arrow(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
// no preconditions // no preconditions
c->lobby_arrow_color = stoull(encode_sjis(args), NULL, 0); c->lobby_arrow_color = stoull(encode_sjis(args), NULL, 0);
if (!l->is_game()) { if (!l->is_game()) {
send_arrow_update(l); send_arrow_update(l);
@@ -432,8 +431,8 @@ static void command_arrow(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Lobby commands // Lobby commands
static void command_cheat(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_cheat(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t*) {
check_is_game(l, true); check_is_game(l, true);
check_is_leader(l, c); check_is_leader(l, c);
@@ -455,7 +454,7 @@ static void command_cheat(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
} }
} }
static void command_lobby_event(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_lobby_event(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, false); check_is_game(l, false);
check_privileges(c, Privilege::ChangeEvent); check_privileges(c, Privilege::ChangeEvent);
@@ -470,7 +469,7 @@ static void command_lobby_event(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
send_change_event(l, l->event); send_change_event(l, l->event);
} }
static void command_lobby_event_all(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_lobby_event_all(shared_ptr<ServerState> s, shared_ptr<Lobby>,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_privileges(c, Privilege::ChangeEvent); check_privileges(c, Privilege::ChangeEvent);
@@ -490,7 +489,7 @@ static void command_lobby_event_all(shared_ptr<ServerState> s, shared_ptr<Lobby>
} }
} }
static void command_lobby_type(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_lobby_type(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, false); check_is_game(l, false);
check_privileges(c, Privilege::ChangeEvent); check_privileges(c, Privilege::ChangeEvent);
@@ -516,7 +515,7 @@ static void command_lobby_type(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Game commands // Game commands
static void command_password(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_password(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, true); check_is_game(l, true);
check_is_leader(l, c); check_is_leader(l, c);
@@ -533,7 +532,7 @@ static void command_password(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
} }
} }
static void command_min_level(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_min_level(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, true); check_is_game(l, true);
check_is_leader(l, c); check_is_leader(l, c);
@@ -544,7 +543,7 @@ static void command_min_level(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
l->min_level + 1); l->min_level + 1);
} }
static void command_max_level(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_max_level(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, true); check_is_game(l, true);
check_is_leader(l, c); check_is_leader(l, c);
@@ -648,16 +647,16 @@ static void command_edit(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
s->send_lobby_join_notifications(l, c); s->send_lobby_join_notifications(l, c);
} }
static void command_change_bank(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_change_bank(shared_ptr<ServerState>, shared_ptr<Lobby>,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t*) {
check_version(c, GameVersion::BB); check_version(c, GameVersion::BB);
// TODO: implement this // TODO: implement this
// TODO: make sure the bank name is filesystem-safe // TODO: make sure the bank name is filesystem-safe
} }
static void command_convert_char_to_bb(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_convert_char_to_bb(shared_ptr<ServerState> s,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Lobby> l, shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, false); check_is_game(l, false);
check_not_version(c, GameVersion::BB); check_not_version(c, GameVersion::BB);
@@ -786,7 +785,7 @@ static void command_ban(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Cheat commands // Cheat commands
static void command_warp(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_warp(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, true); check_is_game(l, true);
check_cheats_enabled(l); check_cheats_enabled(l);
@@ -815,8 +814,8 @@ static void command_warp(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
send_warp(c, area); send_warp(c, area);
} }
static void command_infinite_hp(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_infinite_hp(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t*) {
check_is_game(l, true); check_is_game(l, true);
check_cheats_enabled(l); check_cheats_enabled(l);
@@ -824,8 +823,8 @@ static void command_infinite_hp(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
send_text_message_printf(c, "$C6Infinite HP %s", c->infinite_hp ? "enabled" : "disabled"); send_text_message_printf(c, "$C6Infinite HP %s", c->infinite_hp ? "enabled" : "disabled");
} }
static void command_infinite_tp(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_infinite_tp(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t*) {
check_is_game(l, true); check_is_game(l, true);
check_cheats_enabled(l); check_cheats_enabled(l);
@@ -833,7 +832,7 @@ static void command_infinite_tp(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
send_text_message_printf(c, "$C6Infinite TP %s", c->infinite_tp ? "enabled" : "disabled"); send_text_message_printf(c, "$C6Infinite TP %s", c->infinite_tp ? "enabled" : "disabled");
} }
static void command_item(shared_ptr<ServerState> s, shared_ptr<Lobby> l, static void command_item(shared_ptr<ServerState>, shared_ptr<Lobby> l,
shared_ptr<Client> c, const char16_t* args) { shared_ptr<Client> c, const char16_t* args) {
check_is_game(l, true); check_is_game(l, true);
check_cheats_enabled(l); check_cheats_enabled(l);
View File
View File
+6 -5
View File
@@ -101,23 +101,24 @@ struct prs_compress_ctx {
string prs_compress(const string& data) { string prs_compress(const string& data) {
prs_compress_ctx pc; prs_compress_ctx pc;
ssize_t data_ssize = static_cast<ssize_t>(data.size());
ssize_t read_offset = 0; ssize_t read_offset = 0;
while (read_offset < static_cast<ssize_t>(data.size())) { while (read_offset < data_ssize) {
// look for a chunk of data in history matching what's at the current offset // look for a chunk of data in history matching what's at the current offset
ssize_t best_offset = 0; ssize_t best_offset = 0;
size_t best_size = 0; ssize_t best_size = 0;
for (ssize_t this_offset = -3; for (ssize_t this_offset = -3;
(this_offset + data.size() >= 0) && (this_offset + data_ssize >= 0) &&
(this_offset > -0x1FF0) && (this_offset > -0x1FF0) &&
(best_size < 255); (best_size < 255);
this_offset--) { this_offset--) {
// for this offset, expand the match as much as possible // for this offset, expand the match as much as possible
size_t this_size = 1; ssize_t this_size = 1;
while ((this_size < 0x100) && // max copy size is 255 bytes while ((this_size < 0x100) && // max copy size is 255 bytes
((this_offset + this_size) < 0) && // don't copy past the read offset ((this_offset + this_size) < 0) && // don't copy past the read offset
(this_size <= data.size() - read_offset) && // don't copy past the end (this_size <= data_ssize - read_offset) && // don't copy past the end
!memcmp(data.data() + read_offset + this_offset, !memcmp(data.data() + read_offset + this_offset,
data.data() + read_offset, this_size)) { data.data() + read_offset, this_size)) {
this_size++; this_size++;
+1 -1
View File
@@ -54,7 +54,7 @@ void DNSServer::dispatch_on_receive_message(evutil_socket_t fd,
reinterpret_cast<DNSServer*>(ctx)->on_receive_message(fd, events); reinterpret_cast<DNSServer*>(ctx)->on_receive_message(fd, events);
} }
void DNSServer::on_receive_message(int fd, short event) { void DNSServer::on_receive_message(int fd, short) {
for (;;) { for (;;) {
sockaddr_in remote; sockaddr_in remote;
socklen_t remote_size = sizeof(sockaddr_in); socklen_t remote_size = sizeof(sockaddr_in);
View File
+3 -3
View File
@@ -141,8 +141,7 @@ using namespace std;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void player_use_item(shared_ptr<Lobby> l, shared_ptr<Client> c, void player_use_item(shared_ptr<Client> c, size_t item_index) {
size_t item_index) {
ssize_t equipped_weapon = -1; ssize_t equipped_weapon = -1;
// ssize_t equipped_armor = -1; // ssize_t equipped_armor = -1;
@@ -282,7 +281,8 @@ int32_t CommonItemCreator::decide_item_type(bool is_box) const {
} }
ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode, ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
uint8_t difficulty, uint8_t area, uint8_t section_id) const { uint8_t difficulty, uint8_t area, uint8_t) const {
// TODO: use the section ID (last argument) to vary drop frequencies appropriately
// change the area if it's invalid (data for the bosses are actually in other areas) // change the area if it's invalid (data for the bosses are actually in other areas)
if (area > 10) { if (area > 10) {
if (episode == 1) { if (episode == 1) {
+1 -2
View File
@@ -7,8 +7,7 @@
#include "Lobby.hh" #include "Lobby.hh"
#include "Client.hh" #include "Client.hh"
void player_use_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c, void player_use_item(std::shared_ptr<Client> c, size_t item_index);
size_t item_index);
struct CommonItemCreator { struct CommonItemCreator {
std::vector<uint32_t> enemy_item_categories; std::vector<uint32_t> enemy_item_categories;
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
+6 -6
View File
@@ -108,8 +108,8 @@ void ProxyServer::dispatch_on_server_error(struct bufferevent* bev, short events
void ProxyServer::on_listen_accept(struct evconnlistener* listener, void ProxyServer::on_listen_accept(struct evconnlistener*, evutil_socket_t fd,
evutil_socket_t fd, struct sockaddr* address, int socklen) { struct sockaddr*, int) {
if (this->client_bev.get()) { if (this->client_bev.get()) {
log(WARNING, "ignoring client connection because client already exists"); log(WARNING, "ignoring client connection because client already exists");
@@ -162,15 +162,15 @@ void ProxyServer::on_listen_error(struct evconnlistener* listener) {
event_base_loopexit(this->base.get(), NULL); event_base_loopexit(this->base.get(), NULL);
} }
void ProxyServer::on_client_input(struct bufferevent* bev) { void ProxyServer::on_client_input(struct bufferevent*) {
this->receive_and_process_commands(false); this->receive_and_process_commands(false);
} }
void ProxyServer::on_server_input(struct bufferevent* bev) { void ProxyServer::on_server_input(struct bufferevent*) {
this->receive_and_process_commands(true); this->receive_and_process_commands(true);
} }
void ProxyServer::on_client_error(struct bufferevent* bev, short events) { void ProxyServer::on_client_error(struct bufferevent*, short events) {
if (events & BEV_EVENT_ERROR) { if (events & BEV_EVENT_ERROR) {
int err = EVUTIL_SOCKET_ERROR(); int err = EVUTIL_SOCKET_ERROR();
log(WARNING, "error %d (%s) in client stream", err, log(WARNING, "error %d (%s) in client stream", err,
@@ -190,7 +190,7 @@ void ProxyServer::on_client_error(struct bufferevent* bev, short events) {
} }
} }
void ProxyServer::on_server_error(struct bufferevent* bev, short events) { void ProxyServer::on_server_error(struct bufferevent*, short events) {
if (events & BEV_EVENT_ERROR) { if (events & BEV_EVENT_ERROR) {
int err = EVUTIL_SOCKET_ERROR(); int err = EVUTIL_SOCKET_ERROR();
log(WARNING, "error %d (%s) in server stream", err, log(WARNING, "error %d (%s) in server stream", err,
View File
View File
View File
View File
+77 -78
View File
@@ -156,7 +156,7 @@ void process_disconnect(shared_ptr<ServerState> s, shared_ptr<Client> c) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void process_verify_license_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_verify_license_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // DB uint16_t, uint32_t, uint16_t size, const void* data) { // DB
struct Cmd { struct Cmd {
char unused[0x20]; char unused[0x20];
char serial_number[0x10]; char serial_number[0x10];
@@ -192,7 +192,7 @@ void process_verify_license_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_login_a_dc_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_login_a_dc_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 9A uint16_t, uint32_t, uint16_t size, const void* data) { // 9A
struct Cmd { struct Cmd {
char unused[0x20]; char unused[0x20];
char serial_number[0x10]; char serial_number[0x10];
@@ -232,7 +232,7 @@ void process_login_a_dc_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_login_c_dc_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_login_c_dc_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 9C uint16_t, uint32_t, uint16_t size, const void* data) { // 9C
struct Cmd { struct Cmd {
char unused[8]; char unused[8];
uint32_t sub_version; uint32_t sub_version;
@@ -277,7 +277,7 @@ void process_login_c_dc_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_login_d_e_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_login_d_e_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 9D 9E uint16_t, uint32_t, uint16_t size, const void* data) { // 9D 9E
struct Cmd { struct Cmd {
char unused[0x10]; char unused[0x10];
uint8_t sub_version; uint8_t sub_version;
@@ -335,7 +335,7 @@ void process_login_d_e_pc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_login_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_login_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 93 uint16_t, uint32_t, uint16_t size, const void* data) { // 93
struct Cmd { struct Cmd {
char unused[0x14]; char unused[0x14];
char username[0x10]; char username[0x10];
@@ -403,13 +403,13 @@ void process_login_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
} }
void process_client_checksum(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_client_checksum(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 96 uint16_t, uint32_t, uint16_t, const void*) { // 96
send_command(c, 0x97, 0x01); send_command(c, 0x97, 0x01);
} }
void process_server_time_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_server_time_request(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // B1 uint16_t, uint32_t, uint16_t size, const void*) { // B1
check_size(size, 0); check_size(size, 0);
send_server_time(c); send_server_time(c);
} }
@@ -421,7 +421,7 @@ void process_server_time_request(shared_ptr<ServerState> s, shared_ptr<Client> c
// handlers that partially worked were lost in a dead hard drive, unfortunately. // handlers that partially worked were lost in a dead hard drive, unfortunately.
void process_ep3_jukebox(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_ep3_jukebox(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t command, uint32_t, uint16_t size, const void* data) {
struct Cmd { struct Cmd {
uint32_t unknown[3]; // should be FFFFFFFF 00000000 uint32_t unknown[3]; // should be FFFFFFFF 00000000
}; };
@@ -436,14 +436,14 @@ void process_ep3_jukebox(shared_ptr<ServerState> s, shared_ptr<Client> c,
send_command(l, command, 0x03, cmd); send_command(l, command, 0x03, cmd);
} }
void process_ep3_menu_challenge(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_ep3_menu_challenge(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // DC uint16_t, uint32_t, uint16_t size, const void*) { // DC
check_size(size, 0); check_size(size, 0);
send_command(c, 0xDC); send_command(c, 0xDC);
} }
void process_ep3_server_data_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_ep3_server_data_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // CA uint16_t, uint32_t, uint16_t size, const void* data) { // CA
check_size(size, 8, 0xFFFF); check_size(size, 8, 0xFFFF);
const PSOSubcommand* cmds = reinterpret_cast<const PSOSubcommand*>(data); const PSOSubcommand* cmds = reinterpret_cast<const PSOSubcommand*>(data);
@@ -533,7 +533,7 @@ void process_ep3_server_data_request(shared_ptr<ServerState> s, shared_ptr<Clien
// menu commands // menu commands
void process_message_box_closed(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_message_box_closed(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // D6 uint16_t, uint32_t, uint16_t, const void*) { // D6
if (c->flags & ClientFlag::InInformationMenu) { if (c->flags & ClientFlag::InInformationMenu) {
send_menu(c, u"Information", INFORMATION_MENU_ID, *s->information_menu, false); send_menu(c, u"Information", INFORMATION_MENU_ID, *s->information_menu, false);
} else if (c->flags & ClientFlag::AtWelcomeMessage) { } else if (c->flags & ClientFlag::AtWelcomeMessage) {
@@ -543,7 +543,7 @@ void process_message_box_closed(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_menu_item_info_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_menu_item_info_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 09 uint16_t, uint32_t, uint16_t size, const void* data) { // 09
struct Cmd { struct Cmd {
uint32_t menu_id; uint32_t menu_id;
uint32_t item_id; uint32_t item_id;
@@ -603,7 +603,7 @@ void process_menu_item_info_request(shared_ptr<ServerState> s, shared_ptr<Client
} }
void process_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 10 uint16_t, uint32_t, uint16_t size, const void* data) { // 10
bool uses_unicode = ((c->version == GameVersion::PC) || (c->version == GameVersion::BB)); bool uses_unicode = ((c->version == GameVersion::PC) || (c->version == GameVersion::BB));
struct Cmd { struct Cmd {
@@ -803,7 +803,7 @@ void process_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_change_lobby(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_change_lobby(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 84 uint16_t, uint32_t, uint16_t size, const void* data) { // 84
struct Cmd { struct Cmd {
uint32_t menu_id; uint32_t menu_id;
uint32_t item_id; uint32_t item_id;
@@ -828,13 +828,13 @@ void process_change_lobby(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_game_list_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_game_list_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 08 uint16_t, uint32_t, uint16_t size, const void*) { // 08
check_size(size, 0); check_size(size, 0);
send_game_menu(c, s); send_game_menu(c, s);
} }
void process_change_ship(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_change_ship(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // A0 uint16_t, uint32_t, uint16_t, const void*) { // A0
send_message_box(c, u""); // we do this to avoid the "log window in message box" bug send_message_box(c, u""); // we do this to avoid the "log window in message box" bug
static const vector<string> version_to_port_name({ static const vector<string> version_to_port_name({
@@ -892,7 +892,7 @@ vector<MenuItem> quest_download_menu({
}); });
void process_quest_list_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_quest_list_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // A2 uint16_t, uint32_t flag, uint16_t size, const void*) { // A2
check_size(size, 0); check_size(size, 0);
if (!s->quest_index) { if (!s->quest_index) {
@@ -927,7 +927,7 @@ void process_quest_list_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_quest_ready(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_quest_ready(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // AC uint16_t, uint32_t, uint16_t size, const void*) { // AC
check_size(size, 0); check_size(size, 0);
auto l = s->find_lobby(c->lobby_id); auto l = s->find_lobby(c->lobby_id);
@@ -956,8 +956,8 @@ void process_quest_ready(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
} }
void process_gba_file_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_gba_file_request(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // D7 uint16_t, uint32_t, uint16_t size, const void* data) { // D7
static FileContentsCache file_cache; static FileContentsCache file_cache;
string filename(reinterpret_cast<const char*>(data), size); string filename(reinterpret_cast<const char*>(data), size);
@@ -967,8 +967,8 @@ void process_gba_file_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
send_quest_file(c, filename, *contents, false, false); send_quest_file(c, filename, *contents, false, false);
} }
void process_start_download_quest(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_start_download_quest(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // A6 uint16_t, uint32_t, uint16_t, const void*) { // A6
// TODO implement this // TODO implement this
send_text_message(c, u"$C6Download quests\nare not supported"); send_text_message(c, u"$C6Download quests\nare not supported");
} }
@@ -979,7 +979,7 @@ void process_start_download_quest(shared_ptr<ServerState> s, shared_ptr<Client>
// player data commands // player data commands
void process_player_data(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_player_data(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 61 98 uint16_t command, uint32_t, uint16_t size, const void* data) { // 61 98
// note: we add extra buffer on the end when checking sizes because the // note: we add extra buffer on the end when checking sizes because the
// autoreply text is a variable length // autoreply text is a variable length
@@ -1095,7 +1095,7 @@ void process_chat_generic(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_chat_pc_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_chat_pc_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 06 uint16_t, uint32_t, uint16_t size, const void* data) { // 06
struct Cmd { struct Cmd {
uint32_t unused[2]; uint32_t unused[2];
char16_t text[0]; char16_t text[0];
@@ -1107,7 +1107,7 @@ void process_chat_pc_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_chat_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_chat_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void* data) {
struct Cmd { struct Cmd {
uint32_t unused[2]; uint32_t unused[2];
char text[0]; char text[0];
@@ -1122,14 +1122,14 @@ void process_chat_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// BB commands // BB commands
void process_key_config_request_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_key_config_request_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void*) {
check_size(size, 0); check_size(size, 0);
send_team_and_key_config_bb(c); send_team_and_key_config_bb(c);
} }
void process_player_preview_request_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_player_preview_request_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void* data) {
struct Cmd { struct Cmd {
uint32_t player_index; uint32_t player_index;
uint32_t unused; uint32_t unused;
@@ -1164,8 +1164,8 @@ void process_player_preview_request_bb(shared_ptr<ServerState> s, shared_ptr<Cli
} }
} }
void process_client_checksum_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_client_checksum_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t command, uint32_t, uint16_t size, const void*) {
check_size(size, 0); check_size(size, 0);
if (command == 0x01E8) { if (command == 0x01E8) {
@@ -1177,8 +1177,8 @@ void process_client_checksum_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
} }
void process_guild_card_data_request_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_guild_card_data_request_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void* data) {
struct Cmd { struct Cmd {
uint32_t unknown; uint32_t unknown;
uint32_t chunk_index; uint32_t chunk_index;
@@ -1192,8 +1192,8 @@ void process_guild_card_data_request_bb(shared_ptr<ServerState> s, shared_ptr<Cl
} }
} }
void process_stream_file_request_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_stream_file_request_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t command, uint32_t, uint16_t size, const void*) {
check_size(size, 0); check_size(size, 0);
if (command == 0x04EB) { if (command == 0x04EB) {
@@ -1204,7 +1204,7 @@ void process_stream_file_request_bb(shared_ptr<ServerState> s, shared_ptr<Client
} }
void process_create_character_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_create_character_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void* data) {
struct Cmd { struct Cmd {
uint32_t player_index; uint32_t player_index;
PlayerDispDataBBPreview preview; PlayerDispDataBBPreview preview;
@@ -1262,8 +1262,8 @@ void process_create_character_bb(shared_ptr<ServerState> s, shared_ptr<Client> c
send_approve_player_choice_bb(c); send_approve_player_choice_bb(c);
} }
void process_change_account_data_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_change_account_data_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t command, uint32_t, uint16_t size, const void* data) {
union Cmd { union Cmd {
uint32_t option; // 01ED uint32_t option; // 01ED
uint8_t symbol_chats[0x4E0]; // 02ED uint8_t symbol_chats[0x4E0]; // 02ED
@@ -1309,8 +1309,8 @@ void process_change_account_data_bb(shared_ptr<ServerState> s, shared_ptr<Client
} }
} }
void process_return_player_data_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_return_player_data_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void* data) {
check_size(size, sizeof(PlayerBB)); check_size(size, sizeof(PlayerBB));
const PlayerBB* cmd = reinterpret_cast<const PlayerBB*>(data); const PlayerBB* cmd = reinterpret_cast<const PlayerBB*>(data);
@@ -1324,7 +1324,7 @@ void process_return_player_data_bb(shared_ptr<ServerState> s, shared_ptr<Client>
// Lobby commands // Lobby commands
void process_change_arrow_color(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_change_arrow_color(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 89 uint16_t, uint32_t flag, uint16_t size, const void*) { // 89
check_size(size, 0); check_size(size, 0);
c->lobby_arrow_color = flag; c->lobby_arrow_color = flag;
@@ -1335,7 +1335,7 @@ void process_change_arrow_color(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_card_search(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_card_search(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 40 uint16_t, uint32_t, uint16_t size, const void* data) { // 40
struct Cmd { struct Cmd {
uint32_t player_tag; uint32_t player_tag;
uint32_t searcher_serial_number; uint32_t searcher_serial_number;
@@ -1351,13 +1351,13 @@ void process_card_search(shared_ptr<ServerState> s, shared_ptr<Client> c,
} catch (const out_of_range&) { } } catch (const out_of_range&) { }
} }
void process_choice_search(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_choice_search(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C0 uint16_t, uint32_t, uint16_t, const void*) { // C0
send_text_message(c, u"$C6Choice Search is\nnot supported"); send_text_message(c, u"$C6Choice Search is\nnot supported");
} }
void process_simple_mail(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_simple_mail(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 81 uint16_t, uint32_t, uint16_t size, const void* data) { // 81
if (c->version != GameVersion::GC) { if (c->version != GameVersion::GC) {
// TODO: implement this for DC, PC, BB // TODO: implement this for DC, PC, BB
send_text_message(c, u"$C6Simple Mail is not\nsupported yet on\nthis platform."); send_text_message(c, u"$C6Simple Mail is not\nsupported yet on\nthis platform.");
@@ -1386,15 +1386,14 @@ void process_simple_mail(shared_ptr<ServerState> s, shared_ptr<Client> c,
// if the target has auto-reply enabled, send the autoreply // if the target has auto-reply enabled, send the autoreply
if (target->player.auto_reply[0]) { if (target->player.auto_reply[0]) {
send_simple_mail(c, target->license->serial_number, send_simple_mail(c, target->license->serial_number,
target->player.disp.name, target->player.auto_reply, target->player.disp.name, target->player.auto_reply);
sizeof(target->player.auto_reply));
} }
// forward the message // forward the message
string message(cmd->data, strnlen(cmd->data, sizeof(cmd->data) / sizeof(cmd->data[0]))); string message(cmd->data, strnlen(cmd->data, sizeof(cmd->data) / sizeof(cmd->data[0])));
u16string u16message = decode_sjis(message); u16string u16message = decode_sjis(message);
send_simple_mail(target, c->license->serial_number, c->player.disp.name, send_simple_mail(target, c->license->serial_number, c->player.disp.name,
u16message.data(), u16message.size()); u16message.data());
} }
@@ -1403,26 +1402,26 @@ void process_simple_mail(shared_ptr<ServerState> s, shared_ptr<Client> c,
// Info board commands // Info board commands
void process_info_board_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_info_board_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // D8 uint16_t, uint32_t, uint16_t size, const void*) { // D8
check_size(size, 0); check_size(size, 0);
auto l = s->find_lobby(c->lobby_id); auto l = s->find_lobby(c->lobby_id);
send_info_board(c, l); send_info_board(c, l);
} }
void process_write_info_board_pc_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_write_info_board_pc_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // D9 uint16_t, uint32_t, uint16_t size, const void* data) { // D9
check_size(size, 0, 2 * 0xAC); check_size(size, 0, 2 * 0xAC);
char16cpy(c->player.info_board, reinterpret_cast<const char16_t*>(data), 0xAC); char16cpy(c->player.info_board, reinterpret_cast<const char16_t*>(data), 0xAC);
} }
void process_write_info_board_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_write_info_board_dc_gc(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // D9 uint16_t, uint32_t, uint16_t size, const void* data) { // D9
check_size(size, 0, 0xAC); check_size(size, 0, 0xAC);
decode_sjis(c->player.info_board, reinterpret_cast<const char*>(data), 0xAC); decode_sjis(c->player.info_board, reinterpret_cast<const char*>(data), 0xAC);
} }
void process_set_auto_reply_pc_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_set_auto_reply_pc_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C7 uint16_t, uint32_t, uint16_t size, const void* data) { // C7
check_size(size, 0, 2 * 0xAC); check_size(size, 0, 2 * 0xAC);
if (size == 0) { if (size == 0) {
c->player.auto_reply[0] = 0; c->player.auto_reply[0] = 0;
@@ -1431,8 +1430,8 @@ void process_set_auto_reply_pc_bb(shared_ptr<ServerState> s, shared_ptr<Client>
} }
} }
void process_set_auto_reply_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_set_auto_reply_dc_gc(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C7 uint16_t, uint32_t, uint16_t size, const void* data) { // C7
check_size(size, 0, 0xAC); check_size(size, 0, 0xAC);
if (size == 0) { if (size == 0) {
c->player.auto_reply[0] = 0; c->player.auto_reply[0] = 0;
@@ -1441,14 +1440,14 @@ void process_set_auto_reply_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client>
} }
} }
void process_disable_auto_reply(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_disable_auto_reply(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C8 uint16_t, uint32_t, uint16_t size, const void*) { // C8
check_size(size, 0); check_size(size, 0);
c->player.auto_reply[0] = 0; c->player.auto_reply[0] = 0;
} }
void process_set_blocked_list(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_set_blocked_list(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C6 uint16_t, uint32_t, uint16_t size, const void* data) { // C6
check_size(size, 0x78); check_size(size, 0x78);
memcpy(c->player.blocked, data, 0x78); memcpy(c->player.blocked, data, 0x78);
} }
@@ -1580,7 +1579,7 @@ shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
} }
void process_create_game_pc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_create_game_pc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C1 uint16_t, uint32_t, uint16_t size, const void* data) { // C1
struct Cmd { struct Cmd {
uint32_t unused[2]; uint32_t unused[2];
char16_t name[0x10]; char16_t name[0x10];
@@ -1602,7 +1601,7 @@ void process_create_game_pc(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_create_game_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_create_game_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C1 EC (EC Ep3 only) uint16_t command, uint32_t, uint16_t size, const void* data) { // C1 EC (EC Ep3 only)
struct Cmd { struct Cmd {
uint32_t unused[2]; uint32_t unused[2];
char name[0x10]; char name[0x10];
@@ -1641,7 +1640,7 @@ void process_create_game_dc_gc(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_create_game_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_create_game_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // C1 uint16_t, uint32_t, uint16_t size, const void* data) { // C1
struct Cmd { struct Cmd {
uint32_t unused[2]; uint32_t unused[2];
char16_t name[0x10]; char16_t name[0x10];
@@ -1668,7 +1667,7 @@ void process_create_game_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_lobby_name_request(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_lobby_name_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 8A uint16_t, uint32_t, uint16_t size, const void*) { // 8A
check_size(size, 0); check_size(size, 0);
auto l = s->find_lobby(c->lobby_id); auto l = s->find_lobby(c->lobby_id);
if (!l) { if (!l) {
@@ -1678,7 +1677,7 @@ void process_lobby_name_request(shared_ptr<ServerState> s, shared_ptr<Client> c,
} }
void process_client_ready(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_client_ready(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // 6F uint16_t, uint32_t, uint16_t size, const void*) { // 6F
check_size(size, 0); check_size(size, 0);
auto l = s->find_lobby(c->lobby_id); auto l = s->find_lobby(c->lobby_id);
@@ -1699,8 +1698,8 @@ void process_client_ready(shared_ptr<ServerState> s, shared_ptr<Client> c,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Team commands // Team commands
void process_team_command_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_team_command_bb(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { // EA uint16_t command, uint32_t, uint16_t, const void*) { // EA
if (command == 0x01EA) { if (command == 0x01EA) {
send_lobby_message_box(c, u"$C6Teams are not supported."); send_lobby_message_box(c, u"$C6Teams are not supported.");
@@ -1712,14 +1711,14 @@ void process_team_command_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Patch server commands // Patch server commands
void process_encryption_ok_patch(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_encryption_ok_patch(shared_ptr<ServerState>, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void*) {
check_size(size, 0); check_size(size, 0);
send_command(c, 0x04); // this requests the user's login information send_command(c, 0x04); // this requests the user's login information
} }
void process_login_patch(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_login_patch(shared_ptr<ServerState> s, shared_ptr<Client> c,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t, uint32_t, uint16_t size, const void* data) {
struct Cmd { struct Cmd {
uint32_t unused[3]; uint32_t unused[3];
char username[0x10]; char username[0x10];
@@ -1758,11 +1757,11 @@ License check: ";
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Command pointer arrays // Command pointer arrays
void process_ignored_command(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_ignored_command(shared_ptr<ServerState>, shared_ptr<Client>,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { } uint16_t, uint32_t, uint16_t, const void*) { }
void process_unimplemented_command(shared_ptr<ServerState> s, shared_ptr<Client> c, void process_unimplemented_command(shared_ptr<ServerState>, shared_ptr<Client>,
uint16_t command, uint32_t flag, uint16_t size, const void* data) { uint16_t command, uint32_t flag, uint16_t size, const void*) {
log(WARNING, "unknown command: size=%04X command=%04X flag=%08X\n", log(WARNING, "unknown command: size=%04X command=%04X flag=%08X\n",
size, command, flag); size, command, flag);
throw invalid_argument("unimplemented command"); throw invalid_argument("unimplemented command");
@@ -98,7 +98,7 @@ void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
// Chat commands and the like // Chat commands and the like
// client requests to send a guild card // client requests to send a guild card
static void process_subcommand_send_guild_card(shared_ptr<ServerState> s, static void process_subcommand_send_guild_card(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
check_size(count, 9, 0xFFFF); check_size(count, 9, 0xFFFF);
@@ -120,7 +120,7 @@ static void process_subcommand_send_guild_card(shared_ptr<ServerState> s,
} }
// client sends a symbol chat // client sends a symbol chat
static void process_subcommand_symbol_chat(shared_ptr<ServerState> s, static void process_subcommand_symbol_chat(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
check_size(count, 2, 0xFFFF); check_size(count, 2, 0xFFFF);
@@ -133,7 +133,7 @@ static void process_subcommand_symbol_chat(shared_ptr<ServerState> s,
} }
// client sends a word select chat // client sends a word select chat
static void process_subcommand_word_select(shared_ptr<ServerState> s, static void process_subcommand_word_select(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
check_size(count, 8, 0xFFFF); check_size(count, 8, 0xFFFF);
@@ -161,7 +161,7 @@ static void process_subcommand_word_select(shared_ptr<ServerState> s,
// Game commands used by cheat mechanisms // Game commands used by cheat mechanisms
// need to process changing areas since we keep track of where players are // need to process changing areas since we keep track of where players are
static void process_subcommand_change_area(shared_ptr<ServerState> s, static void process_subcommand_change_area(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
check_size(count, 2, 0xFFFF); check_size(count, 2, 0xFFFF);
@@ -173,7 +173,7 @@ static void process_subcommand_change_area(shared_ptr<ServerState> s,
} }
// when a player is hit by a monster, heal them if infinite HP is enabled // when a player is hit by a monster, heal them if infinite HP is enabled
static void process_subcommand_hit_by_monster(shared_ptr<ServerState> s, static void process_subcommand_hit_by_monster(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (!l->is_game() || (p->byte[2] != c->lobby_client_id)) { if (!l->is_game() || (p->byte[2] != c->lobby_client_id)) {
@@ -186,7 +186,7 @@ static void process_subcommand_hit_by_monster(shared_ptr<ServerState> s,
} }
// when a player casts a tech, restore TP if infinite TP is enabled // when a player casts a tech, restore TP if infinite TP is enabled
static void process_subcommand_use_technique(shared_ptr<ServerState> s, static void process_subcommand_use_technique(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (!l->is_game() || (p->byte[1] != count) || (p->byte[2] != c->lobby_client_id)) { if (!l->is_game() || (p->byte[1] != count) || (p->byte[2] != c->lobby_client_id)) {
@@ -202,7 +202,7 @@ static void process_subcommand_use_technique(shared_ptr<ServerState> s,
// BB Item commands // BB Item commands
// player drops an item // player drops an item
static void process_subcommand_drop_item(shared_ptr<ServerState> s, static void process_subcommand_drop_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -234,7 +234,7 @@ static void process_subcommand_drop_item(shared_ptr<ServerState> s,
} }
// player splits a stack and drops part of it // player splits a stack and drops part of it
static void process_subcommand_drop_stacked_item(shared_ptr<ServerState> s, static void process_subcommand_drop_stacked_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -269,7 +269,7 @@ static void process_subcommand_drop_stacked_item(shared_ptr<ServerState> s,
l->add_item(item); l->add_item(item);
send_drop_stacked_item(l, c, item.data, cmd->area, cmd->x, cmd->y); send_drop_stacked_item(l, item.data, cmd->area, cmd->x, cmd->y);
} else { } else {
forward_subcommand(l, c, command, flag, p, count); forward_subcommand(l, c, command, flag, p, count);
@@ -277,7 +277,7 @@ static void process_subcommand_drop_stacked_item(shared_ptr<ServerState> s,
} }
// player requests to pick up an item // player requests to pick up an item
static void process_subcommand_pick_up_item(shared_ptr<ServerState> s, static void process_subcommand_pick_up_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -310,7 +310,7 @@ static void process_subcommand_pick_up_item(shared_ptr<ServerState> s,
} }
// player equips an item // player equips an item
static void process_subcommand_equip_unequip_item(shared_ptr<ServerState> s, static void process_subcommand_equip_unequip_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -333,7 +333,7 @@ static void process_subcommand_equip_unequip_item(shared_ptr<ServerState> s,
} }
} }
static void process_subcommand_use_item(shared_ptr<ServerState> s, static void process_subcommand_use_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -351,14 +351,14 @@ static void process_subcommand_use_item(shared_ptr<ServerState> s,
c->player.inventory.items[index].game_flags &= 0xFFFFFFF7; // unequip c->player.inventory.items[index].game_flags &= 0xFFFFFFF7; // unequip
} }
player_use_item(l, c, index); player_use_item(c, index);
} }
forward_subcommand(l, c, command, flag, p, count); forward_subcommand(l, c, command, flag, p, count);
} }
static void process_subcommand_open_shop(shared_ptr<ServerState> s, static void process_subcommand_open_shop(shared_ptr<ServerState> s,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
check_size(count, 2); check_size(count, 2);
uint32_t shop_type = p[1].dword; uint32_t shop_type = p[1].dword;
@@ -386,17 +386,17 @@ static void process_subcommand_open_shop(shared_ptr<ServerState> s,
} }
} }
static void process_subcommand_open_bank(shared_ptr<ServerState> s, static void process_subcommand_open_bank(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t,
const PSOSubcommand* p, size_t count) { const PSOSubcommand*, size_t) {
if ((l->version == GameVersion::BB) && l->is_game()) { if ((l->version == GameVersion::BB) && l->is_game()) {
send_bank(c); send_bank(c);
} }
} }
// player performs some bank action // player performs some bank action
static void process_subcommand_bank_action(shared_ptr<ServerState> s, static void process_subcommand_bank_action(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
check_size(count, 4); check_size(count, 4);
@@ -456,8 +456,8 @@ static void process_subcommand_bank_action(shared_ptr<ServerState> s,
} }
// player sorts the items in their inventory // player sorts the items in their inventory
static void process_subcommand_sort_inventory(shared_ptr<ServerState> s, static void process_subcommand_sort_inventory(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
check_size(count, 31); check_size(count, 31);
@@ -635,7 +635,7 @@ static void process_subcommand_box_drop_item(shared_ptr<ServerState> s,
} }
// monster hit by player // monster hit by player
static void process_subcommand_monster_hit(shared_ptr<ServerState> s, static void process_subcommand_monster_hit(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -746,7 +746,7 @@ static void process_subcommand_monster_killed(shared_ptr<ServerState> s,
} }
// destroy item (sent when there are too many items on the ground) // destroy item (sent when there are too many items on the ground)
static void process_subcommand_destroy_item(shared_ptr<ServerState> s, static void process_subcommand_destroy_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -763,7 +763,7 @@ static void process_subcommand_destroy_item(shared_ptr<ServerState> s,
} }
// player requests to tekk an item // player requests to tekk an item
static void process_subcommand_identify_item(shared_ptr<ServerState> s, static void process_subcommand_identify_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (l->version == GameVersion::BB) { if (l->version == GameVersion::BB) {
@@ -822,7 +822,7 @@ static void process_subcommand_identify_item(shared_ptr<ServerState> s,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static void process_subcommand_forward_check_size(shared_ptr<ServerState> s, static void process_subcommand_forward_check_size(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (p->byte[1] != count) { if (p->byte[1] != count) {
@@ -831,7 +831,7 @@ static void process_subcommand_forward_check_size(shared_ptr<ServerState> s,
forward_subcommand(l, c, command, flag, p, count); forward_subcommand(l, c, command, flag, p, count);
} }
static void process_subcommand_forward_check_game(shared_ptr<ServerState> s, static void process_subcommand_forward_check_game(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (!l->is_game()) { if (!l->is_game()) {
@@ -840,7 +840,7 @@ static void process_subcommand_forward_check_game(shared_ptr<ServerState> s,
forward_subcommand(l, c, command, flag, p, count); forward_subcommand(l, c, command, flag, p, count);
} }
static void process_subcommand_forward_check_game_loading(shared_ptr<ServerState> s, static void process_subcommand_forward_check_game_loading(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (!l->is_game() || !l->any_client_loading()) { if (!l->is_game() || !l->any_client_loading()) {
@@ -849,7 +849,7 @@ static void process_subcommand_forward_check_game_loading(shared_ptr<ServerState
forward_subcommand(l, c, command, flag, p, count); forward_subcommand(l, c, command, flag, p, count);
} }
static void process_subcommand_forward_check_size_client(shared_ptr<ServerState> s, static void process_subcommand_forward_check_size_client(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if ((p->byte[1] != count) || (p->byte[2] != c->lobby_client_id)) { if ((p->byte[1] != count) || (p->byte[2] != c->lobby_client_id)) {
@@ -858,7 +858,7 @@ static void process_subcommand_forward_check_size_client(shared_ptr<ServerState>
forward_subcommand(l, c, command, flag, p, count); forward_subcommand(l, c, command, flag, p, count);
} }
static void process_subcommand_forward_check_size_game(shared_ptr<ServerState> s, static void process_subcommand_forward_check_size_game(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (!l->is_game() || (p->byte[1] != count)) { if (!l->is_game() || (p->byte[1] != count)) {
@@ -868,8 +868,8 @@ static void process_subcommand_forward_check_size_game(shared_ptr<ServerState> s
} }
// used for invalid commands. normally, clients should be disconnected - to restore this behavior, change the return value back to SUBCOMMAND_ERROR_INVALID_COMMAND. // used for invalid commands. normally, clients should be disconnected - to restore this behavior, change the return value back to SUBCOMMAND_ERROR_INVALID_COMMAND.
static void process_subcommand_invalid(shared_ptr<ServerState> s, static void process_subcommand_invalid(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby>, shared_ptr<Client>, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (command_is_private(command)) { if (command_is_private(command)) {
log(WARNING, "invalid subcommand: %02X (%d of them) (private to player %d)", log(WARNING, "invalid subcommand: %02X (%d of them) (private to player %d)",
@@ -881,8 +881,8 @@ static void process_subcommand_invalid(shared_ptr<ServerState> s,
} }
// used when an error occurs (unknown commands, etc). normally, clients should be disconnected - to restore this behavior, change the return value back to SUBCOMMAND_ERROR_INVALID_COMMAND. // used when an error occurs (unknown commands, etc). normally, clients should be disconnected - to restore this behavior, change the return value back to SUBCOMMAND_ERROR_INVALID_COMMAND.
static void process_subcommand_unimplemented(shared_ptr<ServerState> s, static void process_subcommand_unimplemented(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag, shared_ptr<Lobby>, shared_ptr<Client>, uint8_t command, uint8_t flag,
const PSOSubcommand* p, size_t count) { const PSOSubcommand* p, size_t count) {
if (command_is_private(command)) { if (command_is_private(command)) {
log(WARNING, "unknown subcommand: %02X (%d of them) (private to player %d)", log(WARNING, "unknown subcommand: %02X (%d of them) (private to player %d)",
+10 -8
View File
@@ -63,6 +63,7 @@ void send_command(shared_ptr<Client> c, uint16_t command, uint32_t flag,
send_data.append(reinterpret_cast<const char*>(data), size); send_data.append(reinterpret_cast<const char*>(data), size);
send_data.resize((send_data.size() + 7) & ~7); send_data.resize((send_data.size() + 7) & ~7);
} }
break;
} }
default: default:
@@ -165,7 +166,7 @@ static void send_server_init_gc(shared_ptr<Client> c, bool initial_connection) {
} }
static void send_server_init_bb(shared_ptr<ServerState> s, shared_ptr<Client> c, static void send_server_init_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
bool initial_connection) { bool) {
struct { struct {
char copyright[0x60]; char copyright[0x60];
uint8_t server_key[0x30]; uint8_t server_key[0x30];
@@ -186,7 +187,7 @@ static void send_server_init_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
sizeof(cmd.client_key))); sizeof(cmd.client_key)));
} }
static void send_server_init_patch(shared_ptr<Client> c, bool initial_connection) { static void send_server_init_patch(shared_ptr<Client> c, bool) {
struct { struct {
char copyright[0x40]; char copyright[0x40];
uint32_t server_key; uint32_t server_key;
@@ -549,7 +550,7 @@ void send_chat_message(shared_ptr<Client> c, uint32_t from_serial_number,
} }
void send_simple_mail_gc(std::shared_ptr<Client> c, uint32_t from_serial_number, void send_simple_mail_gc(std::shared_ptr<Client> c, uint32_t from_serial_number,
const char16_t* from_name, const char16_t* text, size_t max_chars) { const char16_t* from_name, const char16_t* text) {
struct { struct {
uint32_t player_tag; uint32_t player_tag;
uint32_t from_serial_number; uint32_t from_serial_number;
@@ -562,15 +563,15 @@ void send_simple_mail_gc(std::shared_ptr<Client> c, uint32_t from_serial_number,
cmd.from_serial_number = from_serial_number; cmd.from_serial_number = from_serial_number;
encode_sjis(cmd.from_name, from_name, sizeof(cmd.from_name) / sizeof(cmd.from_name[0])); encode_sjis(cmd.from_name, from_name, sizeof(cmd.from_name) / sizeof(cmd.from_name[0]));
cmd.to_serial_number = c->license->serial_number; cmd.to_serial_number = c->license->serial_number;
encode_sjis(cmd.text, c->player.disp.name, sizeof(cmd.text) / sizeof(cmd.text[0])); encode_sjis(cmd.text, text, sizeof(cmd.text) / sizeof(cmd.text[0]));
send_command(c, 0x81, 0x00, cmd); send_command(c, 0x81, 0x00, cmd);
} }
void send_simple_mail(std::shared_ptr<Client> c, uint32_t from_serial_number, void send_simple_mail(std::shared_ptr<Client> c, uint32_t from_serial_number,
const char16_t* from_name, const char16_t* text, size_t max_chars) { const char16_t* from_name, const char16_t* text) {
if (c->version == GameVersion::GC) { if (c->version == GameVersion::GC) {
send_simple_mail_gc(c, from_serial_number, from_name, text, max_chars); send_simple_mail_gc(c, from_serial_number, from_name, text);
} else { } else {
throw logic_error("unimplemented versioned command"); throw logic_error("unimplemented versioned command");
} }
@@ -1862,8 +1863,8 @@ void send_drop_item(shared_ptr<Lobby> l, const ItemData& item,
} }
// notifies other players that a stack was split and part of it dropped (a new item was created) // notifies other players that a stack was split and part of it dropped (a new item was created)
void send_drop_stacked_item(shared_ptr<Lobby> l, shared_ptr<Client> c, void send_drop_stacked_item(shared_ptr<Lobby> l, const ItemData& item,
const ItemData& item, uint8_t area, float x, float y) { uint8_t area, float x, float y) {
struct { struct {
uint8_t subcommand; uint8_t subcommand;
uint8_t subsize; uint8_t subsize;
@@ -1957,6 +1958,7 @@ void send_shop(shared_ptr<Client> c, uint8_t shop_type) {
shop_type, shop_type,
static_cast<uint8_t>(c->player.current_shop_contents.size()), static_cast<uint8_t>(c->player.current_shop_contents.size()),
0, 0,
{},
}; };
size_t count = c->player.current_shop_contents.size(); size_t count = c->player.current_shop_contents.size();
+3 -3
View File
@@ -106,7 +106,7 @@ void send_text_message(std::shared_ptr<ServerState> l, const char16_t* text);
void send_chat_message(std::shared_ptr<Client> c, uint32_t from_serial_number, void send_chat_message(std::shared_ptr<Client> c, uint32_t from_serial_number,
const char16_t* from_name, const char16_t* text); const char16_t* from_name, const char16_t* text);
void send_simple_mail(std::shared_ptr<Client> c, uint32_t from_serial_number, void send_simple_mail(std::shared_ptr<Client> c, uint32_t from_serial_number,
const char16_t* from_name, const char16_t* text, size_t max_chars); const char16_t* from_name, const char16_t* text);
template <typename TARGET> template <typename TARGET>
void send_text_message_printf(std::shared_ptr<TARGET> t, const char* format, ...) { void send_text_message_printf(std::shared_ptr<TARGET> t, const char* format, ...) {
@@ -158,8 +158,8 @@ void send_warp(std::shared_ptr<Client> c, uint32_t area);
void send_drop_item(std::shared_ptr<Lobby> l, const ItemData& item, void send_drop_item(std::shared_ptr<Lobby> l, const ItemData& item,
bool from_enemy, uint8_t area, float x, float y, uint16_t request_id); bool from_enemy, uint8_t area, float x, float y, uint16_t request_id);
void send_drop_stacked_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c, void send_drop_stacked_item(std::shared_ptr<Lobby> l, const ItemData& item,
const ItemData& item, uint8_t area, float x, float y); uint8_t area, float x, float y);
void send_pick_up_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c, uint32_t id, void send_pick_up_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c, uint32_t id,
uint8_t area); uint8_t area);
void send_create_inventory_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c, void send_create_inventory_item(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c,
+1 -1
View File
@@ -85,7 +85,7 @@ void Server::dispatch_on_disconnecting_client_error(struct bufferevent* bev,
} }
void Server::on_listen_accept(struct evconnlistener* listener, void Server::on_listen_accept(struct evconnlistener* listener,
evutil_socket_t fd, struct sockaddr* address, int socklen) { evutil_socket_t fd, struct sockaddr*, int) {
int listen_fd = evconnlistener_get_fd(listener); int listen_fd = evconnlistener_get_fd(listener);
ListeningSocket* listening_socket; ListeningSocket* listening_socket;
View File
+2 -2
View File
@@ -31,7 +31,7 @@ Shell::Shell(std::shared_ptr<struct event_base> base,
this->poll.add(0, POLLIN); this->poll.add(0, POLLIN);
} }
void Shell::dispatch_print_prompt(evutil_socket_t fd, short events, void* ctx) { void Shell::dispatch_print_prompt(evutil_socket_t, short, void* ctx) {
reinterpret_cast<Shell*>(ctx)->print_prompt(); reinterpret_cast<Shell*>(ctx)->print_prompt();
} }
@@ -39,7 +39,7 @@ void Shell::print_prompt() {
// default behavior: no prompt // default behavior: no prompt
} }
void Shell::dispatch_read_stdin(evutil_socket_t fd, short events, void* ctx) { void Shell::dispatch_read_stdin(evutil_socket_t, short, void* ctx) {
reinterpret_cast<Shell*>(ctx)->read_stdin(); reinterpret_cast<Shell*>(ctx)->read_stdin();
} }
View File
View File
View File
View File
View File