Merge master into DC/GC XP boost branch
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "QuestScript.hh"
|
||||
#include "TeamIndex.hh"
|
||||
#include "Text.hh"
|
||||
#include <string>
|
||||
|
||||
extern const uint64_t CLIENT_CONFIG_MAGIC;
|
||||
|
||||
|
||||
+68
-75
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
@@ -33,12 +34,9 @@ const char* BATTLE_TABLE_DISCONNECT_HOOK_NAME = "battle_table_state";
|
||||
const char* QUEST_BARRIER_DISCONNECT_HOOK_NAME = "quest_barrier";
|
||||
const char* ADD_NEXT_CLIENT_DISCONNECT_HOOK_NAME = "add_next_game_client";
|
||||
|
||||
static string bb_test_taint_filename(shared_ptr<Client> c) {
|
||||
return c->character_filename() + ".test-tainted";
|
||||
}
|
||||
|
||||
static string bb_test_taint_grandfather_filename(shared_ptr<Client> c) {
|
||||
return c->character_filename() + ".grandfathered-before-test-taint";
|
||||
static string bb_test_filename(shared_ptr<Client> c) {
|
||||
return c->character_filename() + ".test";
|
||||
}
|
||||
|
||||
static bool file_exists_for_bb_taint(const string& filename) {
|
||||
@@ -46,28 +44,67 @@ static bool file_exists_for_bb_taint(const string& filename) {
|
||||
return f.good();
|
||||
}
|
||||
|
||||
static bool bb_character_is_test_tainted(shared_ptr<Client> c) {
|
||||
return file_exists_for_bb_taint(bb_test_taint_filename(c));
|
||||
static bool bb_character_is_test(shared_ptr<Client> c) {
|
||||
return file_exists_for_bb_taint(bb_test_filename(c));
|
||||
}
|
||||
|
||||
static bool bb_character_is_test_taint_grandfathered(shared_ptr<Client> c) {
|
||||
return file_exists_for_bb_taint(bb_test_taint_grandfather_filename(c));
|
||||
}
|
||||
|
||||
static bool mark_bb_character_test_tainted(shared_ptr<Client> c) {
|
||||
string filename = bb_test_taint_filename(c);
|
||||
static bool mark_bb_character_test(shared_ptr<Client> c) {
|
||||
string filename = bb_test_filename(c);
|
||||
ofstream f(filename, ios::out | ios::trunc);
|
||||
if (!f.good()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
f << "status=test-tainted\n";
|
||||
f << "reason=entered-test-ship\n";
|
||||
f << "account_id=" << c->login->account->account_id << "\n";
|
||||
uint32_t account_id = 0;
|
||||
if (c->login && c->login->account) {
|
||||
account_id = c->login->account->account_id;
|
||||
}
|
||||
|
||||
f << "status=test\n";
|
||||
f << "reason=created-on-test-ship\n";
|
||||
f << "account_id=" << account_id << "\n";
|
||||
f << "character_file=" << c->character_filename() << "\n";
|
||||
return f.good();
|
||||
}
|
||||
|
||||
static void clear_bb_ship_state_markers_for_recreated_character(shared_ptr<Client> c) {
|
||||
const string base_filename = c->character_filename();
|
||||
const vector<string> suffixes = {
|
||||
".hardcore",
|
||||
".hardcore-dead",
|
||||
".hardcore-ineligible",
|
||||
".test",
|
||||
".test-tainted",
|
||||
".grandfathered-before-test-taint",
|
||||
};
|
||||
|
||||
for (const auto& suffix : suffixes) {
|
||||
const string filename = base_filename + suffix;
|
||||
if (file_exists_for_bb_taint(filename)) {
|
||||
if (::unlink(filename.c_str()) == 0) {
|
||||
c->log.info_f("Removed stale BB ship-state marker for recreated character: {}", filename);
|
||||
} else {
|
||||
c->log.warning_f("Failed to remove stale BB ship-state marker for recreated character: {}", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool enforce_bb_test_ship_lock(shared_ptr<Client> c, bool current_ship_is_test) {
|
||||
if (current_ship_is_test) {
|
||||
if (!bb_character_is_test(c)) {
|
||||
send_message_box(c, "$C6Only Test characters can enter Test.\n\n$C7Create a new character on the Test ship.");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (bb_character_is_test(c)) {
|
||||
send_message_box(c, "$C6This BB character is locked to Test.\n\n$C7Test characters cannot enter public ships.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static string bb_hardcore_filename(shared_ptr<Client> c) {
|
||||
return c->character_filename() + ".hardcore";
|
||||
@@ -126,9 +163,7 @@ static bool enforce_bb_hardcore_ship_lock(shared_ptr<Client> c, bool current_shi
|
||||
}
|
||||
|
||||
if (current_ship_is_hardcore) {
|
||||
if (bb_character_is_hardcore_ineligible(c) ||
|
||||
bb_character_is_test_tainted(c) ||
|
||||
bb_character_is_test_taint_grandfathered(c)) {
|
||||
if (bb_character_is_hardcore_ineligible(c)) {
|
||||
if (!bb_character_is_hardcore_ineligible(c)) {
|
||||
mark_bb_character_hardcore_ineligible(c);
|
||||
}
|
||||
@@ -235,8 +270,6 @@ static void send_main_menu(shared_ptr<Client> c) {
|
||||
((c->version() == Version::BB_V4) || (c->version() == Version::BB_PATCH));
|
||||
bool bb_frontdoor_ship_menu = s->enable_bb_ship_selection_menu && is_bb_ship_menu_client;
|
||||
bool bb_destination_transport_menu = !s->enable_bb_ship_selection_menu && is_bb_ship_menu_client;
|
||||
bool show_bb_live_test_menu_items = bb_frontdoor_ship_menu || bb_destination_transport_menu;
|
||||
bool show_bb_restricted_ship_menu_items = bb_frontdoor_ship_menu;
|
||||
|
||||
uint32_t go_to_lobby_menu_item_flags =
|
||||
(s->proxy_destinations_dc.empty() ? 0 : MenuItem::Flag::INVISIBLE_ON_DC) |
|
||||
@@ -302,43 +335,8 @@ static void send_main_menu(shared_ptr<Client> c) {
|
||||
// pre-lobby page and the lobby counter Transport list. Keep the frontdoor
|
||||
// as the full ship selector, but only expose safe transport choices on
|
||||
// destination ships.
|
||||
uint32_t bb_live_test_menu_item_flags =
|
||||
show_bb_live_test_menu_items
|
||||
? MenuItem::Flag::BB_ONLY
|
||||
: (MenuItem::Flag::INVISIBLE_ON_DC |
|
||||
MenuItem::Flag::INVISIBLE_ON_PC |
|
||||
MenuItem::Flag::INVISIBLE_ON_GC |
|
||||
MenuItem::Flag::INVISIBLE_ON_XB |
|
||||
MenuItem::Flag::INVISIBLE_ON_BB);
|
||||
|
||||
uint32_t bb_restricted_ship_menu_item_flags =
|
||||
show_bb_restricted_ship_menu_items
|
||||
? MenuItem::Flag::BB_ONLY
|
||||
: (MenuItem::Flag::INVISIBLE_ON_DC |
|
||||
MenuItem::Flag::INVISIBLE_ON_PC |
|
||||
MenuItem::Flag::INVISIBLE_ON_GC |
|
||||
MenuItem::Flag::INVISIBLE_ON_XB |
|
||||
MenuItem::Flag::INVISIBLE_ON_BB);
|
||||
|
||||
main_menu->items.emplace_back(MainMenuItemID::BB_LIVE_SHIP, "PSO-Peeps Live",
|
||||
"Join the live\nPSO-Peeps ship", bb_live_test_menu_item_flags);
|
||||
main_menu->items.emplace_back(MainMenuItemID::BB_TEST_SHIP, "Test Ship",
|
||||
"Join the test\nconfiguration ship", bb_live_test_menu_item_flags);
|
||||
main_menu->items.emplace_back(MainMenuItemID::BB_DEV_SHIP, "Dev Ship",
|
||||
"Join the dev\nexperimental ship", bb_restricted_ship_menu_item_flags);
|
||||
main_menu->items.emplace_back(MainMenuItemID::BB_VANILLA_SHIP, "Vanilla Ship",
|
||||
"Join the vanilla\ndefault-settings ship", bb_restricted_ship_menu_item_flags);
|
||||
main_menu->items.emplace_back(MainMenuItemID::BB_HARDCORE_SHIP, "Hardcore Ship",
|
||||
"Join the hardcore\npermadeath ship", bb_restricted_ship_menu_item_flags);
|
||||
|
||||
uint32_t proxy_destinations_menu_item_flags =
|
||||
(s->proxy_destinations_dc.empty() ? MenuItem::Flag::INVISIBLE_ON_DC : 0) |
|
||||
(s->proxy_destinations_pc.empty() ? MenuItem::Flag::INVISIBLE_ON_PC : 0) |
|
||||
(s->proxy_destinations_gc.empty() ? MenuItem::Flag::INVISIBLE_ON_GC : 0) |
|
||||
(s->proxy_destinations_xb.empty() ? MenuItem::Flag::INVISIBLE_ON_XB : 0) |
|
||||
MenuItem::Flag::INVISIBLE_ON_BB;
|
||||
main_menu->items.emplace_back(MainMenuItemID::PROXY_DESTINATIONS, "Select ship",
|
||||
"Choose Live,\nVanilla, or Test", proxy_destinations_menu_item_flags);
|
||||
|
||||
main_menu->items.emplace_back(MainMenuItemID::DOWNLOAD_QUESTS, "Download quests",
|
||||
"Download quests", MenuItem::Flag::INVISIBLE_ON_DC_PROTOS | MenuItem::Flag::INVISIBLE_ON_PC_NTE | MenuItem::Flag::INVISIBLE_ON_BB);
|
||||
@@ -2850,14 +2848,6 @@ static asio::awaitable<void> on_10_main_menu(shared_ptr<Client> c, uint32_t item
|
||||
break;
|
||||
}
|
||||
|
||||
// PSO Peeps alpha test: entering Test taints only non-grandfathered BB characters.
|
||||
// Existing characters were grandfathered before this feature was enabled.
|
||||
if (!bb_character_is_test_taint_grandfathered(c)) {
|
||||
if (!mark_bb_character_test_tainted(c)) {
|
||||
send_message_box(c, "$C6Could not mark this character for Test access.\n\n$C7Please report this.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
send_reconnect(c, s->connect_address_for_client(c), 19345);
|
||||
break;
|
||||
@@ -2879,13 +2869,6 @@ static asio::awaitable<void> on_10_main_menu(shared_ptr<Client> c, uint32_t item
|
||||
break;
|
||||
}
|
||||
|
||||
// PSO Peeps dev/test isolation: entering Dev taints only non-grandfathered BB characters.
|
||||
if (!bb_character_is_test_taint_grandfathered(c)) {
|
||||
if (!mark_bb_character_test_tainted(c)) {
|
||||
send_message_box(c, "$C6Could not mark this character for Dev access.\n\n$C7Please report this.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
send_reconnect(c, s->connect_address_for_client(c), 19445);
|
||||
break;
|
||||
@@ -2907,8 +2890,8 @@ static asio::awaitable<void> on_10_main_menu(shared_ptr<Client> c, uint32_t item
|
||||
break;
|
||||
}
|
||||
|
||||
if (bb_character_is_test_tainted(c)) {
|
||||
send_message_box(c, "$C6This character has been used outside of Vanilla and cannot enter Vanilla.\n\n$C7Use Live/Test with this character, or create a fresh Vanilla character.");
|
||||
if (bb_character_is_test(c)) {
|
||||
send_message_box(c, "$C6This BB character is locked to Test.\n\n$C7Test characters cannot enter public ships.");
|
||||
c->channel->disconnect();
|
||||
break;
|
||||
}
|
||||
@@ -2936,8 +2919,7 @@ static asio::awaitable<void> on_10_main_menu(shared_ptr<Client> c, uint32_t item
|
||||
}
|
||||
|
||||
if (bb_character_is_hardcore_ineligible(c) ||
|
||||
bb_character_is_test_tainted(c) ||
|
||||
bb_character_is_test_taint_grandfathered(c)) {
|
||||
bb_character_is_test(c)) {
|
||||
if (!bb_character_is_hardcore_ineligible(c)) {
|
||||
mark_bb_character_hardcore_ineligible(c);
|
||||
}
|
||||
@@ -4164,6 +4146,10 @@ static asio::awaitable<void> on_E3_BB(shared_ptr<Client> c, Channel::Message& ms
|
||||
c->bb_bank_character_index = cmd.character_index;
|
||||
|
||||
auto s = c->require_server_state();
|
||||
if (!enforce_bb_test_ship_lock(c, s->enable_test_mode)) {
|
||||
c->unload_character(false);
|
||||
co_return;
|
||||
}
|
||||
if (!enforce_bb_hardcore_ship_lock(c, s->enable_hardcore_mode)) {
|
||||
c->unload_character(false);
|
||||
co_return;
|
||||
@@ -4415,7 +4401,14 @@ static asio::awaitable<void> on_E5_BB(shared_ptr<Client> c, Channel::Message& ms
|
||||
} else {
|
||||
try {
|
||||
auto s = c->require_server_state();
|
||||
clear_bb_ship_state_markers_for_recreated_character(c);
|
||||
c->create_character_file(c->login->account->account_id, c->language(), cmd.preview, s->level_table(c->version()));
|
||||
if (s->enable_test_mode) {
|
||||
if (!mark_bb_character_test(c)) {
|
||||
throw runtime_error("could not mark new character as Test");
|
||||
}
|
||||
c->log.info_f("Marked BB character as Test: {}", c->character_filename());
|
||||
}
|
||||
} catch (const exception& e) {
|
||||
send_message_box(c, std::format("$C6New character could not be created:\n{}", e.what()));
|
||||
should_send_approve = false;
|
||||
|
||||
@@ -878,6 +878,11 @@ void ServerState::load_config_early() {
|
||||
this->client_ping_interval_usecs = this->config_json->get_int("ClientPingInterval", 30000000);
|
||||
this->client_idle_timeout_usecs = this->config_json->get_int("ClientIdleTimeout", 60000000);
|
||||
this->patch_client_idle_timeout_usecs = this->config_json->get_int("PatchClientIdleTimeout", 300000000);
|
||||
this->psopeeps_dcv2_exp_multiplier = this->config_json->get_int("PsoPeepsDCV2EXPMultiplier", 5);
|
||||
if ((this->psopeeps_dcv2_exp_multiplier != 5) && (this->psopeeps_dcv2_exp_multiplier != 10)) {
|
||||
throw runtime_error("PsoPeepsDCV2EXPMultiplier must be 5 or 10");
|
||||
}
|
||||
|
||||
|
||||
this->ip_stack_debug = this->config_json->get_bool("IPStackDebug", false);
|
||||
this->allow_unregistered_users = this->config_json->get_bool("AllowUnregisteredUsers", false);
|
||||
@@ -952,6 +957,7 @@ void ServerState::load_config_early() {
|
||||
this->enable_bb_ship_selection_menu = this->config_json->get_bool("EnableBBShipSelectionMenu", false);
|
||||
this->enable_blueballz = this->config_json->get_bool("EnableBlueballz", false);
|
||||
this->enable_hardcore_mode = this->config_json->get_bool("EnableHardcoreMode", false);
|
||||
this->enable_test_mode = this->config_json->get_bool("EnableTestMode", false);
|
||||
this->blueballz_max_tier = std::min<int64_t>(10, std::max<int64_t>(0, this->config_json->get_int("BlueballzMaxTier", 10)));
|
||||
this->blueballz_unlocked_tier_v2 = std::min<int64_t>(
|
||||
this->blueballz_max_tier,
|
||||
|
||||
@@ -123,6 +123,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
uint64_t client_ping_interval_usecs = 30000000;
|
||||
uint64_t client_idle_timeout_usecs = 60000000;
|
||||
uint64_t patch_client_idle_timeout_usecs = 300000000;
|
||||
uint64_t psopeeps_dcv2_exp_multiplier = 5;
|
||||
bool is_debug = false;
|
||||
bool ip_stack_debug = false;
|
||||
bool allow_unregistered_users = false;
|
||||
@@ -177,6 +178,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
bool enable_blueballz = false;
|
||||
int64_t blueballz_enemy_hp_scale_tier = -1; // -1 = disabled; 0..10 = scale BB enemy HP in stream files
|
||||
bool enable_hardcore_mode = false;
|
||||
bool enable_test_mode = false;
|
||||
int8_t blueballz_max_tier = 10;
|
||||
int8_t blueballz_unlocked_tier_v2 = 0;
|
||||
int8_t blueballz_unlocked_tier_v3 = 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
.meta key="PsoPeepsEP2EXP10x"
|
||||
.meta name="EP2 10x"
|
||||
.meta client_flag="0x0000200000000000"
|
||||
.meta description="Sets EP2 enemy EXP\nto 10x for GC crossplay"
|
||||
|
||||
.versions 3OE2 3OJ5
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.meta visibility="menu"
|
||||
.meta key="PsoPeepsEP2EXP10xJP"
|
||||
.meta name="EP2 10x"
|
||||
.meta client_flag="0x0000200000000000"
|
||||
.meta description="Sets EP2 enemy EXP\nto 10x for GC crossplay"
|
||||
|
||||
.versions 3OJ5
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
.meta visibility="menu"
|
||||
.meta key="PsoPeepsEP2EXP10xUS"
|
||||
.meta name="EP2 10x"
|
||||
.meta client_flag="0x0000200000000000"
|
||||
.meta description="Sets EP2 enemy EXP\nto 10x for GC crossplay"
|
||||
|
||||
.versions 3OE2
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.meta key="PsoPeepsEP2EXP5x"
|
||||
.meta name="EP2 5x"
|
||||
.meta client_flag="0x0000200000000000"
|
||||
.meta description="Sets EP2 enemy EXP\nto 5x for GC crossplay"
|
||||
|
||||
.versions 3OE2 3OJ5
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.meta visibility="menu"
|
||||
.meta key="PsoPeepsEP2EXP5xJP"
|
||||
.meta name="EP2 5x"
|
||||
.meta client_flag="0x0000200000000000"
|
||||
.meta description="Sets EP2 enemy EXP\nto 5x for GC crossplay"
|
||||
|
||||
.versions 3OJ5
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
.meta visibility="menu"
|
||||
.meta key="PsoPeepsEP2EXP5xUS"
|
||||
.meta name="EP2 5x"
|
||||
.meta client_flag="0x0000200000000000"
|
||||
.meta description="Sets EP2 enemy EXP\nto 5x for GC crossplay"
|
||||
|
||||
.versions 3OE2
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
This file exists to test the patch download system.
|
||||
@@ -0,0 +1 @@
|
||||
{"./Media/PSO/BattleParamEntry.dat":[62976,1777951677030279266,217294441,[333854591,3127350609,1651077234]],"./Media/PSO/newserv-test-pc.txt":[51,1777951677024279220,3510656944,[3510656944]],"./Media/PSO/BattleParamEntry_on.dat":[62976,1777951677030279246,2007581284,[3877699156,780358345,290569120]]}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
This file exists to test the patch download system.
|
||||
Reference in New Issue
Block a user