Files
mtgodot-poc/extension/src/platform/ScriptLib/PythonBoot.h
T
shenleiandClaude Opus 5.5 3e3708ef06 android-native: auto hunt, in-client account registration, mobile UI polish
- Auto hunt (client-only): PythonPlayerAutoHunt.cpp + AutoHuntScript.inc as the
  embedded mt_autohunt module, AUTO touch button, F9/F8.
- Account registration: tools/40250/register_server.py (rc.d mt_register, :11080)
  inserts into account.account; net.RegisterAccount/GetRegisterAccountResult
  (PythonAccountRegister.cpp) and the mt_register login-window dialog
  (RegisterScript.inc).
- --py-exec also runs in --login-screen mode for scripted login-screen tests.
- Touch controller, window manager and render command updates for the
  Android native client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:15:04 +09:00

126 lines
6.3 KiB
C++

#pragma once
// Starting the script layer inside a host process (docs/PORT-PLAN.md 批次 2P step 4).
//
// 40250 runs the interpreter on Main()'s stack (UserInterface/UserInterface.cpp:419-434): construct
// CPythonLauncher, Create(), RunMainScript(), Clear(), all inside one WinMain. Godot owns the process
// here and calls in from GDScript, so the launcher has to outlive the call that starts it — that split
// (Start / RunMainScript / Stop) is the only difference from the original control flow.
//
// It lives under platform/ScriptLib rather than platform/UserInterface because it is only buildable
// with the embedded interpreter, and that is the directory both port_logic and port_platform drop when
// `mtpython` is absent (extension/src/port/CMakeLists.txt).
//
// godot-free, like everything else under platform/: extension/src/python_host_node.cpp is what GDScript
// talks to.
#include <string>
namespace PythonBoot
{
// PythonHost::Configure() -> CPythonLauncher -> Create() -> PythonHost::InstallStdLib(stdlib_path).
// An empty stdlib_path means PythonHost::DefaultStdLibPath(). Starting twice is a no-op that succeeds.
// On failure *error is set and the interpreter is shut down again, so the next attempt starts clean.
// The packs must already be registered (platform/PackBackend.h), as 40250 registers them in Main()
// before the launcher exists.
bool Start(const char* stdlib_path, std::string* error);
bool IsRunning();
// The SDL native client supplies an OS cursor; the Godot host keeps its software cursor.
void SetHostHardwareCursorEnabled(bool enabled);
bool HostHardwareCursorEnabled();
int CursorShape();
bool CursorVisible();
// 40250: RunMainScript(CPythonLauncher&, const char*) — the module initializers, __DEBUG__,
// __COMMAND_LINE__ and RunFile("system.py"). 2V0-e registers temporary observable gameplay modules;
// they are replaced by the real modules in later 2V slices.
// False leaves *error set to what the launcher reported through LogBox (platform/EterBase/LogBox.h).
//
// PORT: system.py runs on a script thread. RunMainScript returns once prototype.RunApp() has reached
// app.Loop() (IsAppLooping) or the script has ended; from then on every AppFrame() runs exactly one
// CPythonApplication::Process() while the host thread waits, so the two never run concurrently.
bool RunMainScript(const char* lpCmdLine, std::string* error);
bool IsAppLooping();
bool AppFrame();
// Native CPythonBackground map selection, in the local coordinate frame of RenderGame.
std::string CurrentMapName();
// Used by the platform CPythonApplication: Loop() calls AppLoopWait() before each Process() and stops
// when it returns false; Exit()/Abort() call AppRequestQuit() (40250: PostQuitMessage).
bool AppLoopWait();
void AppRequestQuit();
// CPythonLauncher::RunLine, with the reported text handed back rather than only shown. The host's own
// check uses it to prove the interpreter and the standard library work in-process on a device that has
// no 40250 packs, which is where RunMainScript cannot run at all.
bool RunLine(const char* source, std::string* error);
// str(expression) evaluated in __main__ (a host/test helper; 40250 has no counterpart).
bool Evaluate(const char* expression, std::string* result, std::string* error);
// Forward physical Godot input to the original 40250 window manager. Coordinates
// are viewport pixels; SetUISize also establishes its logical resolution.
void SetUISize(int width, int height);
// Mobile safe area: the 40250 windows are laid out width - 2 * inset wide and drawn inset pixels
// right of the screen edge (clear of rounded corners and cutouts) while the 3D world keeps the whole
// screen. Input coordinates stay screen pixels. Takes effect at the next SetUISize; 0 = off.
void SetUISafeInset(int inset);
void UIMouseMove(int x, int y);
void UIMouseButton(int button, bool pressed, int x, int y);
void UIMouseWheel(int nLen);
void UIKey(int key, bool pressed);
// Mobile touch & joystick controls
void SetMoveDirection(float angleDeg, bool moving);
void SetAttackKey(bool pressed);
void UseLocalQuickSlot(int localSlotIndex);
bool TryAssignAttachedObjectToLocalQuickSlot(int localSlotIndex);
// PORT: auto hunt (CPythonPlayer::AutoHunt_*, window in AutoHuntScript.inc): start/stop, the settings
// window, and whether it runs / a character is in the world to run it.
void AutoHuntToggle();
void AutoHuntOpenSettings();
bool AutoHuntIsEnabled();
bool AutoHuntAvailable();
// The skill or inventory item in the local quick slot: its UI texture name, the icon's (su, sv, eu, ev)
// inside it and the item count (0 for a skill).
bool LocalQuickSlotIcon(int localSlotIndex, std::string* texture, float uv[4], int* count);
// Touch gestures: a Win32 WM_LBUTTONDBLCLK (40250 CPythonApplication::OnMouseLeftButtonDoubleClick),
// whether an icon hangs on the cursor (CWindowManager::IsAttaching) and mouseController.DeattachObject().
void UIMouseDoubleClick(int x, int y);
bool UIIsAttaching();
void UIDeattachObject();
// Turns the camera around the player immediately, without CCamera::Drag's decaying velocity.
void CameraRotateBy(float rollDeg, float pitchDeg);
bool IsPointInsideActiveUI(int x, int y);
// Touch hosts: hide 40250's on-screen login keypad (the system keyboard types instead).
// Also drops the mouse arrow: touch hosts run 40250's hardware-cursor mode with no OS cursor, so
// mouseModule draws only the attached icon.
void SetTouchInput(bool touch);
bool TouchInput();
// An EditLine has focus (40250 ui.EditLine.OnSetFocus -> ime.EnableCaptureInput).
bool TextInputFocused();
// (x, y) hits the focused window, i.e. the tap landed on the focused EditLine.
bool IsPointInsideFocusedWindow(int x, int y);
struct PlayerStatusInfo {
int level = 1;
int hp = 0;
int max_hp = 0;
int sp = 0;
int max_sp = 0;
int exp = 0;
int max_exp = 0;
std::string name;
};
PlayerStatusInfo GetPlayerStatusInfo();
// WM_CHAR (a Unicode code point) and WM_KEYDOWN (a Win32 VK code) for CPythonIME and OnIMEKeyDown.
void UIChar(unsigned codepoint);
void UIIMEKeyDown(int vkey);
// While IsAppLooping(), UIUpdate is AppFrame() and UIRender keeps the commands that Process() drew.
void UIUpdate();
void UIRender();
// Completed native frame duration, including Vulkan rendering and presentation, for auto sight range.
void SetNativeRenderFrameTime(float milliseconds);
bool IsSoftwareCursorVisible();
// 40250 Main() calls Clear() and lets the launcher leave scope.
void Stop();
}