port 2V2-d.1: ActorInstance/InstanceBase closure creates the main character
Port the ActorInstance*/InstanceBase* siblings plus GameUtil, FlyTarget, PhysicsObject, GameEventManager, WeaponTrace, MapUtil and lineintersect_utils verbatim and drop their pending stand-ins; CGameEventManager and CPythonSystem join PythonBoot in CPythonApplication member order. Root cause of the intermittent Loading-phase header 7: TPlayerSkill::tNextRead is time_t, 32-bit in 40250 (_USE_32BIT_TIME_T) but 64-bit on LP64, so SKILL_LEVEL (76) was read as 2551 bytes instead of 1531. Packet.h now uses LONG with a static_assert, and the fake server sends SKILL_LEVEL in Loading. The fake server's CHARACTER_ADD now uses CHAR_TYPE_PC; port.login_flow asserts the main instance exists with race 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
996d793f0c
commit
5266b00c6e
@@ -404,7 +404,8 @@ bool FakeLoginServer::ServeGame(Connection& c, int index)
|
||||
return Fail(name + ": CG_CHARACTER_SELECT picks an empty slot");
|
||||
Event(name + ":select");
|
||||
|
||||
// CInputDB::PlayerLoad: SetPhase(PHASE_LOADING), CHARACTER::MainCharacterPacket, PointsPacket.
|
||||
// CInputDB::PlayerLoad: SetPhase(PHASE_LOADING), CHARACTER::MainCharacterPacket, PointsPacket,
|
||||
// SkillLevelPacket (1531 bytes; guards the client's 32-bit time_t TPlayerSkill layout).
|
||||
auto main = zeroed<GCMainCharacter>();
|
||||
main.header = HDR_GC_MAIN_CHARACTER;
|
||||
main.vid = kMainVID;
|
||||
@@ -416,7 +417,9 @@ bool FakeLoginServer::ServeGame(Connection& c, int index)
|
||||
auto points = zeroed<GCPoints>();
|
||||
points.header = HDR_GC_CHARACTER_POINTS;
|
||||
points.points[1] = 10; // POINT_LEVEL
|
||||
if (!c.Phase(PHASE_LOADING) || !c.Send(main) || !c.Send(points))
|
||||
auto skill = zeroed<GCSkillLevel>();
|
||||
skill.header = HDR_GC_SKILL_LEVEL;
|
||||
if (!c.Phase(PHASE_LOADING) || !c.Send(main) || !c.Send(points) || !c.Send(skill))
|
||||
return Fail(name + ": send loading packets");
|
||||
|
||||
// The client answers the main character with its version (CInputProcessor::Version).
|
||||
@@ -448,7 +451,7 @@ bool FakeLoginServer::ServeGame(Connection& c, int index)
|
||||
actor.vid = kMainVID;
|
||||
actor.x = kX;
|
||||
actor.y = kY;
|
||||
actor.type = 0; // CHAR_TYPE_PC
|
||||
actor.type = 6; // CHAR_TYPE_PC (common/length.h ECharType)
|
||||
actor.race = 0; // warrior male
|
||||
actor.moving_speed = 100;
|
||||
actor.attack_speed = 100;
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
#include "GameLib/RaceManager.h"
|
||||
#include "GameLib/RaceData.h"
|
||||
#include "GameLib/RaceMotionData.h"
|
||||
#include "UserInterface/StdAfx.h"
|
||||
#include "UserInterface/PythonCharacterManager.h"
|
||||
#include "UserInterface/InstanceBase.h"
|
||||
#include "port_login_flow_server.h"
|
||||
|
||||
#include <memory>
|
||||
@@ -305,6 +308,13 @@ int main(int argc, char** argv)
|
||||
CHECK(CRaceManager::Instance().GetRaceDataPointer(0, &race) && race &&
|
||||
race->GetMotionVectorPointer(CRaceMotionData::MODE_GENERAL, CRaceMotionData::NAME_WAIT, &waits) &&
|
||||
waits && !waits->empty());
|
||||
// (批次 2V2-d) GC_CHARACTER_ADD for the player's own VID went through RecvCharacterAppendPacket and
|
||||
// CNetworkActorManager into CPythonCharacterManager: the main instance exists and SetRace ran on it
|
||||
// (offline the fake server sends a warrior, race 0), and CHAR_ADDITIONAL_INFO found the actor.
|
||||
CInstanceBase* main_instance = CPythonCharacterManager::Instance().GetMainInstancePtr();
|
||||
CHECK(main_instance != nullptr);
|
||||
CHECK(live || (main_instance && main_instance->GetRace() == 0));
|
||||
CHECK(count_syserr("TPacketGCCharacterAdditionalInfo") == 0);
|
||||
}
|
||||
if (server)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user