Files
Viano-Core/tests/clientless/test_portal_transfer.py
T
Nico 1164a72ea3 Implement clientless transports, Lua reload and same-map portals
Add native transport recording and execution with grid lifecycle handling, clientless teleport acknowledgements, and regression tests. Support targeted same-map portal imports and preserve disabled taxi nodes. Document live transport and portal verification and the remaining portal inventory.
2026-10-26 11:27:56 +01:00

84 lines
3.7 KiB
Python

"""Exercise the actual portal handler/ACK/destination checks with Core doubles."""
from pathlib import Path
import subprocess
import tempfile
ROOT = Path(__file__).resolve().parents[2]
source = (ROOT / "src/server/game/World/ClientlessActionExecutorMgr.cpp").read_text()
start = source.index(" WorldPacket areaTriggerPacket(CMSG_AREATRIGGER, 4);")
end = source.index(" record.Status.State = ClientlessActionExecutionState::Moving;", start)
fragment = source[start:end]
assert "same-map portal transition is not supported" not in source
harness = r'''
#include <cassert>
#include <cmath>
#include <string>
#define TC_LOG_WARN(...) ((void)0)
enum class ClientlessActionExecutionState { Idle, Failed, Moving };
constexpr int CMSG_AREATRIGGER=1;
struct WorldPacket { WorldPacket(int,int){} void operator<<(int){} };
struct Player;
struct Session {
Player* p;
int accepted=0,ackCount=0;
bool clientless=true,ackWorks=true;
void HandleAreaTriggerOpcode(WorldPacket&);
void CompleteClientlessTeleport();
bool IsClientless() { return clientless; }
};
struct Player {
int map=1; float x=8393,y=1003,z=30;
bool pending=false,world=true;
Session session{this};
bool IsBeingTeleported() { return pending; }
bool IsBeingTeleportedFar() { return pending&&map==0; }
bool IsInWorld() { return world; }
int GetMapId() { return map; }
float GetPositionX() { return x; } float GetPositionY() { return y; } float GetPositionZ() { return z; }
Session* GetSession() { return &session; }
};
struct Teleport { int target_mapId=1; float target_X=9946,target_Y=2612,target_Z=1316; } destination;
void Session::HandleAreaTriggerOpcode(WorldPacket&) { if (accepted) p->pending=true; }
void Session::CompleteClientlessTeleport() {
++ackCount;
if (!ackWorks) return;
p->pending=false;p->map=destination.target_mapId;
p->x=destination.target_X;p->y=destination.target_Y;p->z=destination.target_Z;
}
struct Record {
struct {ClientlessActionExecutionState State=ClientlessActionExecutionState::Idle; std::string Detail,TargetName;} Status;
bool Active=true;
} record;
struct {int EdgeDatabaseId=1;std::string NodeKey="portal_at_542_target";} step;
bool transfer(Player* player) {
int triggerId=542,characterGuid=26;
auto teleport=&destination;
'''
harness += fragment
harness += r'''
return true;
}
int main() {
Player denied;
assert(!transfer(&denied)&&!record.Active&&record.Status.State==ClientlessActionExecutionState::Failed);
Player near;near.session.accepted=1;record={};
assert(transfer(&near)&&near.session.ackCount==1&&near.map==1&&near.x==9946&&!near.pending);
Player far;far.map=0;far.session.accepted=1;record={};
assert(transfer(&far)&&far.session.ackCount==1&&far.map==1&&!far.pending);
Player pending;pending.session.accepted=1;pending.session.ackWorks=false;record={};
assert(!transfer(&pending)&&pending.pending&&!record.Active);
Player network;network.session.accepted=1;network.session.clientless=false;record={};
assert(!transfer(&network)&&!record.Active);
Player wrongMap;wrongMap.map=0;record={};assert(!transfer(&wrongMap));
Player alreadyAtTarget;alreadyAtTarget.x=destination.target_X;alreadyAtTarget.y=destination.target_Y;alreadyAtTarget.z=destination.target_Z;
record={};assert(transfer(&alreadyAtTarget)); // destination reached independently is valid
}
'''
with tempfile.TemporaryDirectory(prefix="vcore-portal-test-") as folder:
cpp, binary = Path(folder) / "test.cpp", Path(folder) / "test"
cpp.write_text(harness)
subprocess.run(["c++", "-std=c++17", str(cpp), "-o", str(binary)], check=True)
subprocess.run([str(binary)], check=True)
print("Portal near/far ACK and denied same-map transfer regressions passed.")