don't recreate random state for sequential ep3 battles
This commit is contained in:
@@ -54,7 +54,7 @@ public:
|
||||
DeckState(
|
||||
uint8_t client_id,
|
||||
const parray<CardIDT, 0x1F>& card_ids,
|
||||
std::shared_ptr<PSOV2Encryption> random_crypt)
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt)
|
||||
: client_id(client_id),
|
||||
draw_index(1),
|
||||
card_ref_base(this->client_id << 8),
|
||||
@@ -107,7 +107,7 @@ private:
|
||||
parray<CardEntry, 31> entries;
|
||||
parray<uint16_t, 31> card_refs;
|
||||
|
||||
std::shared_ptr<PSOV2Encryption> random_crypt;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
};
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+15
-12
@@ -27,12 +27,12 @@ void ServerBase::PresenceEntry::clear() {
|
||||
ServerBase::ServerBase(
|
||||
shared_ptr<Lobby> lobby,
|
||||
shared_ptr<const DataIndex> data_index,
|
||||
uint32_t random_seed,
|
||||
shared_ptr<PSOLFGEncryption> random_crypt,
|
||||
shared_ptr<const DataIndex::MapEntry> map_if_tournament)
|
||||
: lobby(lobby),
|
||||
data_index(data_index),
|
||||
log(lobby->log.prefix + "[Ep3::Server] "),
|
||||
random_seed(random_seed),
|
||||
random_crypt(random_crypt),
|
||||
is_tournament(!!map_if_tournament),
|
||||
last_chosen_map(map_if_tournament) {}
|
||||
|
||||
@@ -75,6 +75,7 @@ Server::Server(shared_ptr<ServerBase> base)
|
||||
num_pending_attacks(0),
|
||||
client_done_enqueuing_attacks(false),
|
||||
player_ready_to_end_phase(false),
|
||||
random_crypt(base->random_crypt),
|
||||
unknown_a10(0),
|
||||
overall_time_expired(false),
|
||||
battle_start_usecs(0),
|
||||
@@ -102,9 +103,12 @@ Server::Server(shared_ptr<ServerBase> base)
|
||||
void Server::init() {
|
||||
this->card_special.reset(new CardSpecial(this->shared_from_this()));
|
||||
|
||||
// The default PSOV2Encryption constructor in the original implementation just
|
||||
// uses 0 as the seed. We'll replace this object later when the battle starts.
|
||||
this->random_crypt.reset(new PSOV2Encryption(0));
|
||||
// Note: The original implementation calls the default PSOV2Encryption
|
||||
// constructor for random_crypt, which just uses 0 as the seed. It then
|
||||
// re-seeds the generator later. We instead expect the caller to provide a
|
||||
// seeded generator, and we don't re-seed it at all.
|
||||
// this->random_crypt.reset(new PSOV2Encryption(0));
|
||||
|
||||
this->state_flags.reset(new StateFlags());
|
||||
|
||||
this->clear_player_flags_after_dice_phase();
|
||||
@@ -213,8 +217,7 @@ void Server::send_6xB4x46() const {
|
||||
G_ServerVersionStrings_GC_Ep3_6xB4x46 cmd46;
|
||||
cmd46.version_signature = VERSION_SIGNATURE;
|
||||
cmd46.date_str1 = format_time(this->base()->data_index->card_definitions_mtime() * 1000000);
|
||||
cmd46.date_str2 = string_printf("Lobby/%08" PRIX32 " random %08" PRIX32,
|
||||
l->lobby_id, l->random_seed);
|
||||
cmd46.date_str2 = string_printf("Lobby/%08" PRIX32, l->lobby_id);
|
||||
this->send(cmd46);
|
||||
}
|
||||
|
||||
@@ -1171,8 +1174,8 @@ void Server::set_client_id_ready_to_advance_phase(uint8_t client_id) {
|
||||
// TODO: It'd be nice to do this in a constant-randomness way, but I'm
|
||||
// lazy, and this matches Sega's original implementation. The less-lazy
|
||||
// way to do it would be to roll three dice: one in the range [1, N],
|
||||
// one in the range [3, N], and on in the range [1, 2] to decide whether
|
||||
// to swap the first two results.
|
||||
// one in the range [3, N], and one in the range [1, 2] to decide
|
||||
// whether to swap the first two results.
|
||||
for (size_t z = 0; z < 200; z++) {
|
||||
ps->roll_main_dice();
|
||||
if ((ps->get_atk_points() >= 3) || (ps->get_def_points() >= 3)) {
|
||||
@@ -1302,9 +1305,9 @@ void Server::set_player_deck_valid(uint8_t client_id) {
|
||||
|
||||
void Server::setup_and_start_battle() {
|
||||
this->setup_phase = SetupPhase::STARTER_ROLLS;
|
||||
// Note: The original implementation uses time() as the random seed; we use a
|
||||
// user-settable value in order to support replays and deterministic testing
|
||||
this->random_crypt.reset(new PSOV2Encryption(this->base()->random_seed));
|
||||
|
||||
// Note: This is where original implementation re-seeds random_crypt (it uses
|
||||
// time() as the seed value).
|
||||
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
if (!this->check_presence_entry(z)) {
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
ServerBase(
|
||||
std::shared_ptr<Lobby> lobby,
|
||||
std::shared_ptr<const DataIndex> data_index,
|
||||
uint32_t random_seed,
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt,
|
||||
std::shared_ptr<const DataIndex::MapEntry> map_if_tournament);
|
||||
void init();
|
||||
void reset();
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
std::weak_ptr<Lobby> lobby;
|
||||
std::shared_ptr<const DataIndex> data_index;
|
||||
PrefixedLogger log;
|
||||
uint32_t random_seed;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
bool is_tournament;
|
||||
std::shared_ptr<const DataIndex::MapEntry> last_chosen_map;
|
||||
|
||||
@@ -258,7 +258,7 @@ public:
|
||||
uint32_t num_pending_attacks;
|
||||
parray<uint8_t, 4> client_done_enqueuing_attacks;
|
||||
parray<uint8_t, 4> player_ready_to_end_phase;
|
||||
std::shared_ptr<PSOV2Encryption> random_crypt;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
uint32_t unknown_a10;
|
||||
uint32_t overall_time_expired;
|
||||
// Note: In the original implementation, this is a uint32_t and is measured in
|
||||
|
||||
@@ -22,7 +22,6 @@ Lobby::Lobby(uint32_t id)
|
||||
mode(GameMode::NORMAL),
|
||||
difficulty(0),
|
||||
random_seed(random_object<uint32_t>()),
|
||||
random(new mt19937(this->random_seed)),
|
||||
event(0),
|
||||
block(0),
|
||||
type(0),
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
std::u16string name;
|
||||
// This seed is also sent to the client for rare enemy generation
|
||||
uint32_t random_seed;
|
||||
std::shared_ptr<std::mt19937> random;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
std::shared_ptr<ItemCreator> item_creator;
|
||||
|
||||
// Ep3 stuff
|
||||
|
||||
+4
-3
@@ -4,6 +4,7 @@
|
||||
#include <phosg/Strings.hh>
|
||||
|
||||
#include "Loggers.hh"
|
||||
#include "PSOEncryption.hh"
|
||||
#include "StaticGameData.hh"
|
||||
|
||||
using namespace std;
|
||||
@@ -665,7 +666,7 @@ const vector<vector<AreaMapFileIndex>>& map_file_info_for_episode(Episode ep) {
|
||||
|
||||
void generate_variations(
|
||||
parray<le_uint32_t, 0x20>& variations,
|
||||
shared_ptr<mt19937> random,
|
||||
shared_ptr<PSOLFGEncryption> random_crypt,
|
||||
Episode episode,
|
||||
bool is_solo) {
|
||||
const auto& ep_index = map_file_info_for_episode(episode);
|
||||
@@ -681,8 +682,8 @@ void generate_variations(
|
||||
variations[z * 2 + 0] = 0;
|
||||
variations[z * 2 + 1] = 0;
|
||||
} else {
|
||||
variations[z * 2 + 0] = (a->variation1_values.size() < 2) ? 0 : ((*random)() % a->variation1_values.size());
|
||||
variations[z * 2 + 1] = (a->variation2_values.size() < 2) ? 0 : ((*random)() % a->variation2_values.size());
|
||||
variations[z * 2 + 0] = (a->variation1_values.size() < 2) ? 0 : (random_crypt->next() % a->variation1_values.size());
|
||||
variations[z * 2 + 1] = (a->variation2_values.size() < 2) ? 0 : (random_crypt->next() % a->variation2_values.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "PSOEncryption.hh"
|
||||
#include "StaticGameData.hh"
|
||||
#include "Text.hh"
|
||||
|
||||
@@ -117,7 +118,7 @@ private:
|
||||
|
||||
void generate_variations(
|
||||
parray<le_uint32_t, 0x20>& variations,
|
||||
std::shared_ptr<std::mt19937> random,
|
||||
std::shared_ptr<PSOLFGEncryption> random,
|
||||
Episode episode,
|
||||
bool is_solo);
|
||||
std::vector<std::string> map_filenames_for_variation(
|
||||
|
||||
@@ -1322,7 +1322,7 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
}
|
||||
auto tourn = l->tournament_match ? l->tournament_match->tournament.lock() : nullptr;
|
||||
l->ep3_server_base = make_shared<Episode3::ServerBase>(
|
||||
l, s->ep3_data_index, l->random_seed, tourn ? tourn->get_map() : nullptr);
|
||||
l, s->ep3_data_index, l->random_crypt, tourn ? tourn->get_map() : nullptr);
|
||||
l->ep3_server_base->init();
|
||||
|
||||
if (s->ep3_behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES) {
|
||||
@@ -1331,7 +1331,6 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
send_text_message_printf(l->clients[z], "Your client ID: $C6%zu", z);
|
||||
}
|
||||
}
|
||||
send_text_message_printf(l, "State seed: $C6%08" PRIX32, l->random_seed);
|
||||
}
|
||||
|
||||
if (s->ep3_behavior_flags & Episode3::BehaviorFlag::ENABLE_RECORDING) {
|
||||
@@ -3167,8 +3166,8 @@ shared_ptr<Lobby> create_game_generic(
|
||||
game->difficulty = difficulty;
|
||||
if (c->options.override_random_seed >= 0) {
|
||||
game->random_seed = c->options.override_random_seed;
|
||||
game->random->seed(game->random_seed);
|
||||
}
|
||||
game->random_crypt.reset(new PSOV2Encryption(game->random_seed));
|
||||
if (battle_player) {
|
||||
game->battle_player = battle_player;
|
||||
battle_player->set_lobby(game);
|
||||
@@ -3204,7 +3203,7 @@ shared_ptr<Lobby> create_game_generic(
|
||||
if (game->is_ep3() || (c->version() == GameVersion::DC && (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE)))) {
|
||||
game->variations.clear(0);
|
||||
} else {
|
||||
generate_variations(game->variations, game->random, game->episode, is_solo);
|
||||
generate_variations(game->variations, game->random_crypt, game->episode, is_solo);
|
||||
}
|
||||
|
||||
if (game->version == GameVersion::BB) {
|
||||
|
||||
@@ -3372,10 +3372,6 @@ I 48349 2023-05-26 15:59:20 - [Commands] Sending to C-4 (Tali) (version=GC comma
|
||||
0010 | 20 63 6C 69 65 6E 74 20 49 44 3A 20 09 43 36 30 | client ID: C60
|
||||
0020 | 00 00 00 00 |
|
||||
I 48349 2023-05-26 15:59:20 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 28 00 00 00 00 00 00 00 00 00 53 74 61 74 | ( Stat
|
||||
0010 | 65 20 73 65 65 64 3A 20 09 43 36 34 34 34 34 34 | e seed: C644444
|
||||
0020 | 34 34 34 00 00 00 00 00 | 444
|
||||
I 48349 2023-05-26 15:59:20 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 24 00 00 00 00 00 00 00 00 00 09 43 36 52 | $ C6R
|
||||
0010 | 65 63 6F 72 64 69 6E 67 20 65 6E 61 62 6C 65 64 | ecording enabled
|
||||
0020 | 00 00 00 00 |
|
||||
@@ -25143,10 +25139,6 @@ I 48349 2023-05-26 16:04:46 - [Commands] Sending to C-4 (Tali) (version=GC comma
|
||||
0010 | 20 63 6C 69 65 6E 74 20 49 44 3A 20 09 43 36 30 | client ID: C60
|
||||
0020 | 00 00 00 00 |
|
||||
I 48349 2023-05-26 16:04:46 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 28 00 00 00 00 00 00 00 00 00 53 74 61 74 | ( Stat
|
||||
0010 | 65 20 73 65 65 64 3A 20 09 43 36 34 34 34 34 34 | e seed: C644444
|
||||
0020 | 34 34 34 00 00 00 00 00 | 444
|
||||
I 48349 2023-05-26 16:04:46 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 24 00 00 00 00 00 00 00 00 00 09 43 36 52 | $ C6R
|
||||
0010 | 65 63 6F 72 64 69 6E 67 20 63 6F 6D 70 6C 65 74 | ecording complet
|
||||
0020 | 65 00 00 00 | e
|
||||
|
||||
Reference in New Issue
Block a user